Skip to content

Commit e917c85

Browse files
committed
Fix legacy recommended config
Fixes #14
1 parent becdd76 commit e917c85

File tree

5 files changed

+103
-40
lines changed

5 files changed

+103
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Add the plugin's recommended config to your ESLint configuration file.
2929
```js
3030
{
3131
"extends": [
32-
"plugin:react-you-might-not-need-an-effect/recommended"
32+
"plugin:react-you-might-not-need-an-effect/legacy-recommended"
3333
],
3434
}
3535
```

src/index.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,41 @@ const plugin = {
77
meta: {
88
name: pluginName,
99
},
10-
configs: {
11-
recommended: {},
12-
},
10+
configs: {},
1311
rules: {
1412
[ruleName]: rule,
1513
},
1614
};
1715

18-
Object.assign(plugin.configs.recommended, {
19-
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"],
20-
plugins: {
21-
// Object.assign above so we can reference `plugin` here
22-
[pluginName]: plugin,
23-
},
24-
rules: {
25-
[pluginName + "/" + ruleName]: "warn",
16+
Object.assign(plugin.configs, {
17+
// flat config format
18+
recommended: {
19+
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}"],
20+
plugins: {
21+
// Object.assign above so we can reference `plugin` here
22+
[pluginName]: plugin,
23+
},
24+
rules: {
25+
[pluginName + "/" + ruleName]: "warn",
26+
},
27+
languageOptions: {
28+
globals: {
29+
// NOTE: Required so we can resolve global references to their upstream global variables
30+
...globals.browser,
31+
},
32+
parserOptions: {
33+
ecmaFeatures: {
34+
jsx: true,
35+
},
36+
},
37+
},
2638
},
27-
languageOptions: {
39+
// eslintrc format
40+
"legacy-recommended": {
41+
plugins: [pluginName],
42+
rules: {
43+
[pluginName + "/" + ruleName]: "warn",
44+
},
2845
globals: {
2946
// NOTE: Required so we can resolve global references to their upstream global variables
3047
...globals.browser,

test/config.test.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { ESLint } from "eslint";
2+
import plugin from "../src/index.js";
3+
import assert from "assert";
4+
import { js } from "./rule-tester.js";
5+
import { LegacyESLint } from "eslint/use-at-your-own-risk";
6+
7+
describe("Recommended config", () => {
8+
const code = js`
9+
import { useState, useEffect } from "react";
10+
11+
const MyComponent = () => {
12+
const [state, setState] = useState(0);
13+
const [otherState, setOtherState] = useState(0);
14+
15+
useEffect(() => {
16+
setState(otherState * 2);
17+
}, [state]);
18+
};
19+
`;
20+
21+
const runLintTest = async (eslintInstance, code) => {
22+
const results = await eslintInstance.lintText(code);
23+
24+
assert.strictEqual(results.length, 1);
25+
assert.ok(results[0].messages);
26+
assert.ok(
27+
results[0].messages.some(
28+
(message) =>
29+
message.ruleId ===
30+
"react-you-might-not-need-an-effect/you-might-not-need-an-effect",
31+
),
32+
);
33+
};
34+
35+
it("Flat", async () => {
36+
await runLintTest(
37+
new ESLint({
38+
// Use `overrideConfig` so it ignores the project's config
39+
overrideConfig: [plugin.configs.recommended],
40+
}),
41+
code,
42+
);
43+
});
44+
45+
it("Legacy", async () => {
46+
await runLintTest(
47+
new LegacyESLint({
48+
overrideConfig: {
49+
extends: [
50+
"plugin:react-you-might-not-need-an-effect/legacy-recommended",
51+
],
52+
parserOptions: {
53+
// To support the syntax in the code under test
54+
ecmaVersion: 2020,
55+
sourceType: "module",
56+
},
57+
},
58+
}),
59+
code,
60+
);
61+
});
62+
});

test/rule-tester.js

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,15 @@
1-
// eslint-disable-next-line n/no-unsupported-features/node-builtins
2-
import assert from "node:assert";
1+
import assert from "assert";
32
import { RuleTester } from "eslint";
4-
import { name as ruleName, rule as myRule } from "../src/rule.js";
5-
import globals from "globals";
3+
import plugin from "../src/index.js";
64

75
// For syntax highlighting inside code under test
86
export const js = String.raw;
97

10-
// Generic name I know, but it does a couple things, and inheritance is annoying.
11-
//
12-
// Normalizes whitespaces between the expected and actual `output` for tests with fixes.
13-
// Because formatting seriously complicates the fixer implementation and most people have a formatter anyway.
14-
// Not sure how hacky this is.
15-
// Seems like it might be standard practice for ESLint plugins?
16-
// Even the TS ESLint plugin mentions that it does not concern itself with formatting.
17-
//
18-
// Supports labelling tests as `todo` (and there's always more to do).
198
export class MyRuleTester extends RuleTester {
209
constructor(options) {
2110
super({
2211
...options,
23-
languageOptions: {
24-
globals: {
25-
// We use these in tests frequently
26-
...globals.browser,
27-
},
28-
parserOptions: {
29-
ecmaFeatures: {
30-
jsx: true,
31-
},
32-
},
33-
},
12+
languageOptions: plugin.configs.recommended.languageOptions,
3413
});
3514
}
3615

@@ -61,7 +40,11 @@ export class MyRuleTester extends RuleTester {
6140
invalid: invalid.filter((test) => !test.todo),
6241
};
6342

64-
super.run(ruleName + variation, myRule, filteredTests);
43+
super.run(
44+
plugin.meta.name + variation,
45+
plugin.rules["you-might-not-need-an-effect"],
46+
filteredTests,
47+
);
6548
} finally {
6649
// Restore the original strictEqual function to avoid unintended effects
6750
assert.strictEqual = originalStrictEqual;

types/index.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { ESLint } from "eslint";
1+
import type { ESLint, Linter } from "eslint";
22

33
declare const plugin: ESLint.Plugin & {
44
configs: {
5-
recommended: ESLint.ConfigData;
5+
recommended: Linter.Config;
6+
"legacy-recommended": Linter.LegacyConfig;
67
};
78
};
89
export default plugin;

0 commit comments

Comments
 (0)