Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions tests/autofix.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,18 @@ describe("autofix", () => {

expect(result.output).toBe('read -r line\necho "$line"\n');
});

it("should apply fixes from multiple rules at once", () => {
const result = fix("read name\necho `pwd` $name\n", {
"shell/require-read-r": "error",
"shell/no-backticks": "error",
"shell/no-unquoted-expansions": "error",
});

expect(result.fixed).toBe(true);

// The backticks become $(pwd) in the first pass, and the second
// pass quotes the now-unquoted substitution.
expect(result.output).toBe('read -r name\necho "$(pwd)" "$name"\n');
});
});
106 changes: 106 additions & 0 deletions tests/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,109 @@ describe("recommended configuration", () => {
);
});
});

describe("shipped rules", () => {
it("should run multiple rules together", () => {
const messages = lint(
[
"cd /var/log",
"for f in $(ls); do",
" echo $f",
"done",
"cat error.log | grep error",
"",
].join("\n"),
{
"shell/require-cd-guard": "error",
"shell/no-ls-iteration": "error",
"shell/no-unquoted-expansions": "error",
"shell/no-useless-cat": "error",
},
);
const ruleIds = new Set(messages.map(message => message.ruleId));

expect(ruleIds).toEqual(
new Set([
"shell/no-ls-iteration",
"shell/no-unquoted-expansions",
"shell/no-useless-cat",
"shell/require-cd-guard",
]),
);
});

it("should report rules from the recommended config", () => {
const linter = new Linter();
const messages = linter.verify(
"echo `pwd`\n",
[shell.configs.recommended] as never,
"script.sh",
);

expect(
messages.some(message => message.ruleId === "shell/no-backticks"),
).toBe(true);
});

it("should flag a script with typical ShellCheck findings", () => {
const linter = new Linter();
const code = [
"#!/bin/bash",
"unused=1",
"cd /tmp",
"read input",
"echo $input",
"",
].join("\n");
const messages = linter.verify(
code,
[shell.configs.recommended] as never,
"script.sh",
);
const ruleIds = new Set(messages.map(message => message.ruleId));

expect(ruleIds).toContain("shell/no-unused-vars");
expect(ruleIds).toContain("shell/require-cd-guard");
expect(ruleIds).toContain("shell/require-read-r");
expect(ruleIds).toContain("shell/no-unquoted-expansions");
});

it("should not report a well-written script", () => {
const linter = new Linter();
const code = [
"#!/bin/bash",
"set -euo pipefail",
'cd "$(dirname "$0")" || exit',
"while read -r line; do",
" printf '%s\\n' \"$line\"",
"done < input.txt",
"for f in *.txt; do",
' echo "$f"',
"done",
"",
].join("\n");
const messages = linter.verify(
code,
[shell.configs.recommended] as never,
"script.sh",
);

expect(messages).toEqual([]);
});

it.each(["shell/bash", "shell/posix", "shell/mksh"])(
"should run the recommended rules with the %s language",
language => {
const linter = new Linter();
const messages = linter.verify(
'echo "`pwd`"\n',
[{ ...shell.configs.recommended, language }] as never,
"script.sh",
);

expect(messages.map(message => message.ruleId)).toEqual([
"shell/no-backticks",
]);
},
);
});
Loading