@open-xchange/linter-presets 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.0] - 2024-08-15
4
+
5
+ - added: [ESLint] option `testingLib` for environment `env.vitest`
6
+ - added: [ESLint] plugins `testing-library`, `jest-dom`, and option `testingLib` for environment `env.jest`
7
+ - added: [ESLint] option `jestDom` for environments `env.jest` and `env.vitest`
8
+ - chore: bump dependencies
9
+
3
10
  ## [0.4.3] - 2024-08-08
4
11
 
5
12
  - chore: bump dependencies
@@ -1,5 +1,5 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
- import type { EnvRestrictedOptions } from "../shared/env-utils.js";
2
+ import type { EnvRestrictedOptions } from "../shared/restricted.js";
3
3
  /**
4
4
  * Configuration options for the environment preset "env.browser".
5
5
  */
@@ -1,6 +1,7 @@
1
1
  import JAVASCRIPT_GLOBALS from "globals";
2
2
  import CONFUSING_BROWSER_GLOBALS from "confusing-browser-globals";
3
- import { concatConfigs, createConfig, restrictedRules, customRules } from "../shared/env-utils.js";
3
+ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js";
4
+ import { restrictedRules } from "../shared/restricted.js";
4
5
  // constants ==================================================================
5
6
  /**
6
7
  * Global builtin symbols that are confusing or deprecated.
@@ -1,9 +1,9 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
- import type { EnvBaseOptions } from "../shared/env-utils.js";
2
+ import { type EnvUnitTestOptions } from "../shared/unittest.js";
3
3
  /**
4
4
  * Configuration options for the environment preset "env.jest".
5
5
  */
6
- export interface EnvJestOptions extends EnvBaseOptions {
6
+ export interface EnvJestOptions extends EnvUnitTestOptions {
7
7
  }
8
8
  /**
9
9
  * Creates configuration objects with global symbols and linter rules for unit
@@ -11,6 +11,7 @@ export interface EnvJestOptions extends EnvBaseOptions {
11
11
  *
12
12
  * Wraps the following packages:
13
13
  * - `eslint-plugin-jest`
14
+ * - `eslint-plugin-testing-library`
14
15
  *
15
16
  * @param envOptions
16
17
  * Configuration options for the environment.
@@ -1,5 +1,6 @@
1
1
  import jestPlugin from "eslint-plugin-jest";
2
2
  import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js";
3
+ import { createUnitTestPluginConfigs } from "../shared/unittest.js";
3
4
  // functions ==================================================================
4
5
  /**
5
6
  * Creates configuration objects with global symbols and linter rules for unit
@@ -7,6 +8,7 @@ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js
7
8
  *
8
9
  * Wraps the following packages:
9
10
  * - `eslint-plugin-jest`
11
+ * - `eslint-plugin-testing-library`
10
12
  *
11
13
  * @param envOptions
12
14
  * Configuration options for the environment.
@@ -19,9 +21,9 @@ export default function jest(envOptions) {
19
21
  // register rule implementations, globals, and recommended rules
20
22
  createConfig(envOptions, jestPlugin.configs["flat/recommended"]),
21
23
  // add recommended stylistic rules
22
- createConfig(envOptions, {
23
- rules: jestPlugin.configs["flat/style"].rules,
24
- }),
24
+ createConfig(envOptions, jestPlugin.configs["flat/style"]),
25
+ // "jest-dom" and "testing-library" plugin
26
+ createUnitTestPluginConfigs(envOptions),
25
27
  // custom rules
26
28
  customRules(envOptions, {
27
29
  "jest/consistent-test-it": ["error", { fn: "it" }],
@@ -1,6 +1,7 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
2
  import type ts from "typescript";
3
- import type { LanguageOptions, EnvRestrictedOptions } from "../shared/env-utils.js";
3
+ import type { LanguageOptions } from "../shared/env-utils.js";
4
+ import { type EnvRestrictedOptions } from "../shared/restricted.js";
4
5
  export type EnvNodeConvertPathPattern = [pattern: string, replacement: string];
5
6
  export type EnvNodeConvertPathObject = Record<string, EnvNodeConvertPathPattern>;
6
7
  export interface EnvNodeConvertPathArray {
@@ -1,5 +1,6 @@
1
1
  import nodePlugin from "eslint-plugin-n";
2
- import { concatConfigs, createConfig, restrictedRules, customRules } from "../shared/env-utils.js";
2
+ import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js";
3
+ import { restrictedRules } from "../shared/restricted.js";
3
4
  // functions ==================================================================
4
5
  /**
5
6
  * Creates configuration objects with global symbols and linter rules for
@@ -1,9 +1,9 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
- import type { EnvBaseOptions } from "../shared/env-utils.js";
2
+ import { type EnvUnitTestOptions } from "../shared/unittest.js";
3
3
  /**
4
4
  * Configuration options for the environment preset "env.vitest".
5
5
  */
6
- export interface EnvVitestOptions extends EnvBaseOptions {
6
+ export interface EnvVitestOptions extends EnvUnitTestOptions {
7
7
  }
8
8
  /**
9
9
  * Creates configuration objects with global symbols and linter rules for unit
@@ -1,8 +1,6 @@
1
1
  import vitestPlugin from "eslint-plugin-vitest";
2
- import jestDomPlugin from "eslint-plugin-jest-dom";
3
- import testingLibraryPlugin from "eslint-plugin-testing-library";
4
- import { fixupPluginRules } from "@eslint/compat";
5
2
  import { concatConfigs, createConfig, customRules } from "../shared/env-utils.js";
3
+ import { createUnitTestPluginConfigs } from "../shared/unittest.js";
6
4
  // functions ==================================================================
7
5
  /**
8
6
  * Creates configuration objects with global symbols and linter rules for unit
@@ -34,17 +32,8 @@ export default function vitest(envOptions) {
34
32
  // recommended rules
35
33
  rules: vitestPlugin.configs.recommended.rules,
36
34
  }),
37
- // "jest-dom" plugin
38
- createConfig(envOptions, jestDomPlugin.configs["flat/recommended"]),
39
- // "testing-library" plugin
40
- createConfig(envOptions, {
41
- // register rule implementations of the plugins
42
- plugins: {
43
- "testing-library": fixupPluginRules(testingLibraryPlugin), // https://github.com/testing-library/eslint-plugin-testing-library/issues/899
44
- },
45
- // recommended rules
46
- rules: testingLibraryPlugin.configs.react.rules,
47
- }),
35
+ // "jest-dom" and "testing-library" plugin
36
+ createUnitTestPluginConfigs(envOptions),
48
37
  // custom rules
49
38
  customRules(envOptions, {
50
39
  // "vitest" plugin
@@ -69,7 +58,5 @@ export default function vitest(envOptions) {
69
58
  "vitest/prefer-to-contain": "error",
70
59
  "vitest/prefer-to-have-length": "error",
71
60
  "vitest/require-top-level-describe": "error",
72
- // "testing-library" plugin
73
- "testing-library/no-node-access": ["error", { allowContainerFirstChild: true }],
74
61
  }));
75
62
  }
@@ -84,79 +84,6 @@ export interface EnvBaseOptions extends EnvFilesOptions {
84
84
  */
85
85
  rules?: TSESLint.FlatConfig.Rules;
86
86
  }
87
- /**
88
- * Configuration for a single banned global or import.
89
- */
90
- export interface EnvRestrictedName {
91
- name: string;
92
- message: string;
93
- }
94
- /**
95
- * Configuration for a single banned object property.
96
- */
97
- export interface EnvRestrictedProperty {
98
- object: string;
99
- property: string;
100
- message: string;
101
- }
102
- /**
103
- * Configuration for a single banned syntax construct.
104
- */
105
- export interface EnvRestrictedSyntax {
106
- selector: string;
107
- message: string;
108
- }
109
- /**
110
- * Collection of banned globals, imports, properties, and syntax constructs.
111
- */
112
- export interface EnvRestrictedItems {
113
- /** The global symbols to be banned. */
114
- globals?: EnvRestrictedName[];
115
- /** The module imports to be banned. */
116
- imports?: EnvRestrictedName[];
117
- /** The global object properties to be banned. */
118
- properties?: EnvRestrictedProperty[];
119
- /** The syntax constructs to be banned. */
120
- syntax?: EnvRestrictedSyntax[];
121
- }
122
- /**
123
- * Collection of banned globals, imports, properties, and syntax constructs,
124
- * for a specific subset of the files included in an environment.
125
- */
126
- export interface EnvRestrictedOverride extends EnvFilesOptions, EnvRestrictedItems {
127
- }
128
- /**
129
- * Type shape of a dedicated environment option "restricted" with settings for
130
- * banned globals, imports, properties, and syntax constructs.
131
- */
132
- export interface EnvRestrictedOption extends EnvRestrictedItems {
133
- /**
134
- * Whether the environment supports native decorators. In this case, it
135
- * will be required to replace TypeScript decorated `private` methods with
136
- * native `#private` methods.
137
- *
138
- * Default value is `false` (TypeScript's experimental decorators cannot be
139
- * used with native `#private` fields).
140
- */
141
- nativeDecorators?: boolean;
142
- /**
143
- * Overrides for specific subsets of files in the environment. All
144
- * restricted items of overrides will be merged with the common restricted
145
- * items defined for the entire environment.
146
- */
147
- overrides?: EnvRestrictedOverride[];
148
- }
149
- /**
150
- * Shared options for an environment preset: include and exclude files, add
151
- * more linter rules, and settings for restricted items.
152
- */
153
- export interface EnvRestrictedOptions extends EnvBaseOptions {
154
- /**
155
- * All globals, imports, properties, and syntax constructs to be banned for
156
- * the files included by the environment.
157
- */
158
- restricted?: EnvRestrictedOption;
159
- }
160
87
  /**
161
88
  * Shared options for the core rule `no-unused-vars`, and the plugin rule
162
89
  * `@typescript-eslint/no-unused-vars`.
@@ -168,6 +95,20 @@ export declare const NO_UNUSED_VARS_OPTIONS: {
168
95
  caughtErrors: string;
169
96
  ignoreRestSiblings: boolean;
170
97
  };
98
+ /**
99
+ * Concatenates and flattens multiple elements or arrays into a single array
100
+ * while skipping all falsy parameters.
101
+ *
102
+ * @template T
103
+ * The type of the array elements.
104
+ *
105
+ * @param entries
106
+ * The elements or arrays to be concatenated.
107
+ *
108
+ * @returns
109
+ * The concatenated and flattened array.
110
+ */
111
+ export declare function flatArray<T>(...entries: Array<T | T[] | false | null | undefined>): T[];
171
112
  /**
172
113
  * Concatenates multiple configuration objects or arrays into an array while
173
114
  * skipping all falsy parameters.
@@ -178,7 +119,7 @@ export declare const NO_UNUSED_VARS_OPTIONS: {
178
119
  * @returns
179
120
  * The concatenated configuration array.
180
121
  */
181
- export declare const concatConfigs: (...entries: (TSESLint.FlatConfig.Config | TSESLint.FlatConfig.Config[] | undefined)[]) => TSESLint.FlatConfig.Config[];
122
+ export declare const concatConfigs: (...entries: (false | TSESLint.FlatConfig.Config | TSESLint.FlatConfig.Config[] | null | undefined)[]) => TSESLint.FlatConfig.Config[];
182
123
  /**
183
124
  * Creates a flat configuration object with "files" and "ignores" settings from
184
125
  * an environment's "envOptions" object.
@@ -190,24 +131,13 @@ export declare const concatConfigs: (...entries: (TSESLint.FlatConfig.Config | T
190
131
  * Properties for the flat configuration to be built. Additional "files" and
191
132
  * "ignores" properties will be merged with the settings from "envOptions".
192
133
  *
193
- * @returns
194
- * The resulting flat configuration object.
195
- */
196
- export declare function createConfig(envOptions: EnvFilesOptions, flatConfig: TSESLint.FlatConfig.Config): TSESLint.FlatConfig.Config;
197
- /**
198
- * Generates various "no-restricted-?" rules from the passed configuration.
199
- *
200
- * @param envOptions
201
- * The environment options containing "files", "ignores", and "restricted"
202
- * settings.
203
- *
204
- * @param fixed
205
- * The fixed restricted items provided by the environment preset.
134
+ * @param rules
135
+ * Hard-coded rule settings to be added to the configuration.
206
136
  *
207
137
  * @returns
208
- * The flat configuration objects needed to forbid the restricted items.
138
+ * The resulting flat configuration object.
209
139
  */
210
- export declare function restrictedRules(envOptions: EnvRestrictedOptions, fixed?: EnvRestrictedItems): TSESLint.FlatConfig.ConfigArray;
140
+ export declare function createConfig(envOptions: EnvFilesOptions, flatConfig: TSESLint.FlatConfig.Config, rules?: TSESLint.FlatConfig.Rules): TSESLint.FlatConfig.Config;
211
141
  /**
212
142
  * Creates a flat configuration object with "files", "ignores", and "rules"
213
143
  * settings from an environment's "envOptions" object.
@@ -24,34 +24,9 @@ export const NO_UNUSED_VARS_OPTIONS = {
24
24
  * @returns
25
25
  * The concatenated and flattened array.
26
26
  */
27
- function flatten(...entries) {
28
- return entries.flatMap(array => array ?? []);
27
+ export function flatArray(...entries) {
28
+ return entries.flatMap(array => array || []);
29
29
  }
30
- /**
31
- * Creates a rules record for all restricted items.
32
- *
33
- * @param generator
34
- * The generator callback function that returns the restricted items to be
35
- * inserted into the linter rules.
36
- *
37
- * @returns
38
- * The rules record containing entries for all existing restricted items.
39
- */
40
- function createRulesRecord(generator) {
41
- const rules = {};
42
- for (const key of ["globals", "imports", "properties", "syntax"]) {
43
- const items = generator(key);
44
- if (items?.length) {
45
- rules[`no-restricted-${key}`] = ["error", ...items];
46
- }
47
- }
48
- // same restrictions for CommonJS `require` as for `import` statements
49
- if ("no-restricted-imports" in rules) {
50
- rules["no-restricted-modules"] = rules["no-restricted-imports"];
51
- }
52
- return rules;
53
- }
54
- // ----------------------------------------------------------------------------
55
30
  /**
56
31
  * Concatenates multiple configuration objects or arrays into an array while
57
32
  * skipping all falsy parameters.
@@ -62,7 +37,7 @@ function createRulesRecord(generator) {
62
37
  * @returns
63
38
  * The concatenated configuration array.
64
39
  */
65
- export const concatConfigs = (flatten);
40
+ export const concatConfigs = (flatArray);
66
41
  /**
67
42
  * Creates a flat configuration object with "files" and "ignores" settings from
68
43
  * an environment's "envOptions" object.
@@ -74,57 +49,19 @@ export const concatConfigs = (flatten);
74
49
  * Properties for the flat configuration to be built. Additional "files" and
75
50
  * "ignores" properties will be merged with the settings from "envOptions".
76
51
  *
52
+ * @param rules
53
+ * Hard-coded rule settings to be added to the configuration.
54
+ *
77
55
  * @returns
78
56
  * The resulting flat configuration object.
79
57
  */
80
- export function createConfig(envOptions, flatConfig) {
58
+ export function createConfig(envOptions, flatConfig, rules) {
81
59
  return {
82
60
  ...flatConfig,
83
- files: flatten(envOptions.files, flatConfig.files),
84
- ignores: flatten(envOptions.ignores, flatConfig.ignores),
85
- };
86
- }
87
- /**
88
- * Generates various "no-restricted-?" rules from the passed configuration.
89
- *
90
- * @param envOptions
91
- * The environment options containing "files", "ignores", and "restricted"
92
- * settings.
93
- *
94
- * @param fixed
95
- * The fixed restricted items provided by the environment preset.
96
- *
97
- * @returns
98
- * The flat configuration objects needed to forbid the restricted items.
99
- */
100
- export function restrictedRules(envOptions, fixed) {
101
- const { restricted = {} } = envOptions;
102
- const RESTRICTED_GLOBALS = [
103
- { name: "isFinite", message: "Use 'Number.isFinite' instead." },
104
- { name: "isNaN", message: "Use 'Number.isNaN' instead." },
105
- ];
106
- const RESTRICTED_SYNTAX = [
107
- { selector: ":matches(PropertyDefinition, MethodDefinition[kind!='constructor'])[accessibility='public']", message: "Remove 'public' keyword." },
108
- { selector: ":matches(PropertyDefinition, MethodDefinition[kind!='constructor'])[accessibility='private']" + (restricted.nativeDecorators ? "" : "[decorators.length=0]"), message: "Use #private syntax instead." },
109
- { selector: "MethodDefinition[kind='constructor'] TSParameterProperty[accessibility]", message: "Use explicit class properties." },
110
- ];
111
- // restricted items for all files in the environment
112
- const items = {
113
- globals: flatten(RESTRICTED_GLOBALS, fixed?.globals, restricted.globals),
114
- imports: flatten(fixed?.imports, restricted.imports),
115
- properties: flatten(fixed?.properties, restricted.properties),
116
- syntax: flatten(RESTRICTED_SYNTAX, fixed?.syntax, restricted.syntax),
61
+ files: flatArray(envOptions.files, flatConfig.files),
62
+ ignores: flatArray(envOptions.ignores, flatConfig.ignores),
63
+ rules: { ...flatConfig.rules, ...rules },
117
64
  };
118
- // generate the configuration objects
119
- return concatConfigs(
120
- // base rules for all files in the environment
121
- createConfig(envOptions, {
122
- rules: createRulesRecord(key => items[key]),
123
- }),
124
- // generate the override entries (join with base items)
125
- restricted.overrides?.map(override => createConfig(override, {
126
- rules: createRulesRecord(key => flatten(items[key], override[key])),
127
- })));
128
65
  }
129
66
  /**
130
67
  * Creates a flat configuration object with "files", "ignores", and "rules"
@@ -0,0 +1,89 @@
1
+ import type { TSESLint } from "@typescript-eslint/utils";
2
+ import type { EnvFilesOptions, EnvBaseOptions } from "../shared/env-utils.js";
3
+ /**
4
+ * Configuration for a single banned global or import.
5
+ */
6
+ export interface EnvRestrictedName {
7
+ name: string;
8
+ message: string;
9
+ }
10
+ /**
11
+ * Configuration for a single banned object property.
12
+ */
13
+ export interface EnvRestrictedProperty {
14
+ object: string;
15
+ property: string;
16
+ message: string;
17
+ }
18
+ /**
19
+ * Configuration for a single banned syntax construct.
20
+ */
21
+ export interface EnvRestrictedSyntax {
22
+ selector: string;
23
+ message: string;
24
+ }
25
+ /**
26
+ * Collection of banned globals, imports, properties, and syntax constructs.
27
+ */
28
+ export interface EnvRestrictedItems {
29
+ /** The global symbols to be banned. */
30
+ globals?: EnvRestrictedName[];
31
+ /** The module imports to be banned. */
32
+ imports?: EnvRestrictedName[];
33
+ /** The global object properties to be banned. */
34
+ properties?: EnvRestrictedProperty[];
35
+ /** The syntax constructs to be banned. */
36
+ syntax?: EnvRestrictedSyntax[];
37
+ }
38
+ /**
39
+ * Collection of banned globals, imports, properties, and syntax constructs,
40
+ * for a specific subset of the files included in an environment.
41
+ */
42
+ export interface EnvRestrictedOverride extends EnvFilesOptions, EnvRestrictedItems {
43
+ }
44
+ /**
45
+ * Type shape of a dedicated environment option "restricted" with settings for
46
+ * banned globals, imports, properties, and syntax constructs.
47
+ */
48
+ export interface EnvRestrictedOption extends EnvRestrictedItems {
49
+ /**
50
+ * Whether the environment supports native decorators. In this case, it
51
+ * will be required to replace TypeScript decorated `private` methods with
52
+ * native `#private` methods.
53
+ *
54
+ * Default value is `false` (TypeScript's experimental decorators cannot be
55
+ * used with native `#private` fields).
56
+ */
57
+ nativeDecorators?: boolean;
58
+ /**
59
+ * Overrides for specific subsets of files in the environment. All
60
+ * restricted items of overrides will be merged with the common restricted
61
+ * items defined for the entire environment.
62
+ */
63
+ overrides?: EnvRestrictedOverride[];
64
+ }
65
+ /**
66
+ * Shared options for an environment preset: include and exclude files, add
67
+ * more linter rules, and settings for restricted items.
68
+ */
69
+ export interface EnvRestrictedOptions extends EnvBaseOptions {
70
+ /**
71
+ * All globals, imports, properties, and syntax constructs to be banned for
72
+ * the files included by the environment.
73
+ */
74
+ restricted?: EnvRestrictedOption;
75
+ }
76
+ /**
77
+ * Generates various "no-restricted-?" rules from the passed configuration.
78
+ *
79
+ * @param envOptions
80
+ * The environment options containing "files", "ignores", and "restricted"
81
+ * settings.
82
+ *
83
+ * @param fixed
84
+ * The fixed restricted items provided by the environment preset.
85
+ *
86
+ * @returns
87
+ * The flat configuration objects needed to forbid the restricted items.
88
+ */
89
+ export declare function restrictedRules(envOptions: EnvRestrictedOptions, fixed?: EnvRestrictedItems): TSESLint.FlatConfig.ConfigArray;
@@ -0,0 +1,69 @@
1
+ import { flatArray, concatConfigs, createConfig } from "../shared/env-utils.js";
2
+ // functions ==================================================================
3
+ /**
4
+ * Creates a rules record for all restricted items.
5
+ *
6
+ * @param generator
7
+ * The generator callback function that returns the restricted items to be
8
+ * inserted into the linter rules.
9
+ *
10
+ * @returns
11
+ * The rules record containing entries for all existing restricted items.
12
+ */
13
+ function createRulesRecord(generator) {
14
+ const rules = {};
15
+ for (const key of ["globals", "imports", "properties", "syntax"]) {
16
+ const items = generator(key);
17
+ if (items?.length) {
18
+ rules[`no-restricted-${key}`] = ["error", ...items];
19
+ }
20
+ }
21
+ // same restrictions for CommonJS `require` as for `import` statements
22
+ if ("no-restricted-imports" in rules) {
23
+ rules["no-restricted-modules"] = rules["no-restricted-imports"];
24
+ }
25
+ return rules;
26
+ }
27
+ // ----------------------------------------------------------------------------
28
+ /**
29
+ * Generates various "no-restricted-?" rules from the passed configuration.
30
+ *
31
+ * @param envOptions
32
+ * The environment options containing "files", "ignores", and "restricted"
33
+ * settings.
34
+ *
35
+ * @param fixed
36
+ * The fixed restricted items provided by the environment preset.
37
+ *
38
+ * @returns
39
+ * The flat configuration objects needed to forbid the restricted items.
40
+ */
41
+ export function restrictedRules(envOptions, fixed) {
42
+ const { restricted = {} } = envOptions;
43
+ const RESTRICTED_GLOBALS = [
44
+ { name: "isFinite", message: "Use 'Number.isFinite' instead." },
45
+ { name: "isNaN", message: "Use 'Number.isNaN' instead." },
46
+ ];
47
+ const RESTRICTED_SYNTAX = [
48
+ { selector: ":matches(PropertyDefinition, MethodDefinition[kind!='constructor'])[accessibility='public']", message: "Remove 'public' keyword." },
49
+ { selector: ":matches(PropertyDefinition, MethodDefinition[kind!='constructor'])[accessibility='private']" + (restricted.nativeDecorators ? "" : "[decorators.length=0]"), message: "Use #private syntax instead." },
50
+ { selector: "MethodDefinition[kind='constructor'] TSParameterProperty[accessibility]", message: "Use explicit class properties." },
51
+ ];
52
+ // restricted items for all files in the environment
53
+ const items = {
54
+ globals: flatArray(RESTRICTED_GLOBALS, fixed?.globals, restricted.globals),
55
+ imports: flatArray(fixed?.imports, restricted.imports),
56
+ properties: flatArray(fixed?.properties, restricted.properties),
57
+ syntax: flatArray(RESTRICTED_SYNTAX, fixed?.syntax, restricted.syntax),
58
+ };
59
+ // generate the configuration objects
60
+ return concatConfigs(
61
+ // base rules for all files in the environment
62
+ createConfig(envOptions, {
63
+ rules: createRulesRecord(key => items[key]),
64
+ }),
65
+ // generate the override entries (join with base items)
66
+ restricted.overrides?.map(override => createConfig(override, {
67
+ rules: createRulesRecord(key => flatArray(items[key], override[key])),
68
+ })));
69
+ }
@@ -0,0 +1,29 @@
1
+ import type { TSESLint } from "@typescript-eslint/utils";
2
+ import { type EnvBaseOptions } from "./env-utils.js";
3
+ /**
4
+ * Shared options for environment presets for unit tests.
5
+ */
6
+ export interface EnvUnitTestOptions extends EnvBaseOptions {
7
+ /**
8
+ * Specifies whether to include `eslint-plugin-jest-dom`. Should only be
9
+ * used, if the package `jest-dom` has been installed in the project.
10
+ * Default value is `false`.
11
+ */
12
+ jestDom?: boolean;
13
+ /**
14
+ * Specifies the recommended rule set of `eslint-plugin-testing-library` to
15
+ * be included.
16
+ */
17
+ testingLib?: "angular" | "dom" | "marko" | "react" | "vue";
18
+ }
19
+ /**
20
+ * Conditionally creates flat configuration objects for the ESLint plugins
21
+ * `eslint-plugin-jest-dom` and `eslint-plugin-testing-library`.
22
+ *
23
+ * @param envOptions
24
+ * The configuration options for the unit test environment.
25
+ *
26
+ * @returns
27
+ * The resulting flat configuration objects.
28
+ */
29
+ export declare function createUnitTestPluginConfigs(envOptions: EnvUnitTestOptions): TSESLint.FlatConfig.ConfigArray;
@@ -0,0 +1,32 @@
1
+ import jestDomPlugin from "eslint-plugin-jest-dom";
2
+ import testingLibraryPlugin from "eslint-plugin-testing-library";
3
+ import { fixupPluginRules } from "@eslint/compat";
4
+ import { concatConfigs, createConfig } from "./env-utils.js";
5
+ // functions ==================================================================
6
+ /**
7
+ * Conditionally creates flat configuration objects for the ESLint plugins
8
+ * `eslint-plugin-jest-dom` and `eslint-plugin-testing-library`.
9
+ *
10
+ * @param envOptions
11
+ * The configuration options for the unit test environment.
12
+ *
13
+ * @returns
14
+ * The resulting flat configuration objects.
15
+ */
16
+ export function createUnitTestPluginConfigs(envOptions) {
17
+ return concatConfigs(
18
+ // "jest-dom" plugin
19
+ envOptions.jestDom && createConfig(envOptions, jestDomPlugin.configs["flat/recommended"]),
20
+ // "testing-library" plugin
21
+ envOptions.testingLib && createConfig(envOptions, {
22
+ // register rule implementations of the plugins
23
+ plugins: {
24
+ "testing-library": fixupPluginRules(testingLibraryPlugin), // https://github.com/testing-library/eslint-plugin-testing-library/issues/899
25
+ },
26
+ // recommended rules
27
+ rules: {
28
+ ...testingLibraryPlugin.configs.react.rules,
29
+ "testing-library/no-node-access": ["error", { allowContainerFirstChild: true }],
30
+ },
31
+ }));
32
+ }
@@ -1,6 +1,10 @@
1
1
  # Environment `env.jest`
2
2
 
3
- Creates configuration objects with global symbols and linter rules for unit tests using Jest. Adds the plugin [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) and its recommended rules.
3
+ Creates configuration objects with global symbols and linter rules for unit tests using Jest. Adds the following plugins and their recommended rules:
4
+
5
+ - [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest)
6
+ - [eslint-plugin-jest-dom](https://github.com/testing-library/eslint-plugin-jest-dom) (optional)
7
+ - [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library) (optional)
4
8
 
5
9
  ## Signature
6
10
 
@@ -15,6 +19,8 @@ function jest(options: EnvJestOptions): Linter.FlatConfig[]
15
19
  | `files` | `string[]` | _required_ | Glob patterns for source files to be included. |
16
20
  | `ignores` | `string[]` | `[]` | Glob patterns for source files matching `files` to be ignored. |
17
21
  | `rules` | `Linter.RulesRecord` | `{}` | Additional linter rules to be added to the configuration. |
22
+ | `jestDom` | `boolean` | `false` | Activate plugin `eslint-plugin-jest-dom`. |
23
+ | `testingLib` | `"angular"\|"dom"\|"marko"\|"react"\|"vue"` | _none_ | Activate plugin `eslint-plugin-testing-library` for the specified environment. |
18
24
 
19
25
  ## Example
20
26
 
@@ -26,6 +32,7 @@ export default [
26
32
  ...eslint.configure({ /* ... */ }),
27
33
  ...eslint.env.jest({
28
34
  files: ["test/**/*.{js,ts}"],
35
+ testingLib: "react",
29
36
  rules: { /* ... */ },
30
37
  }),
31
38
  ]
@@ -3,8 +3,8 @@
3
3
  Creates configuration objects with global symbols and linter rules for unit tests using Vitest. Adds the following plugins and their recommended rules:
4
4
 
5
5
  - [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest)
6
- - [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library)
7
- - [eslint-plugin-jest-dom](https://github.com/testing-library/eslint-plugin-jest-dom)
6
+ - [eslint-plugin-jest-dom](https://github.com/testing-library/eslint-plugin-jest-dom) (optional)
7
+ - [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library) (optional)
8
8
 
9
9
  ## Signature
10
10
 
@@ -19,6 +19,8 @@ function vitest(options: EnvVitestOptions): Linter.FlatConfig[]
19
19
  | `files` | `string[]` | _required_ | Glob patterns for source files to be included. |
20
20
  | `ignores` | `string[]` | `[]` | Glob patterns for source files matching `files` to be ignored. |
21
21
  | `rules` | `Linter.RulesRecord` | `{}` | Additional linter rules to be added to the configuration. |
22
+ | `jestDom` | `boolean` | `false` | Activate plugin `eslint-plugin-jest-dom`. |
23
+ | `testingLib` | `"angular"\|"dom"\|"marko"\|"react"\|"vue"` | _none_ | Add plugin `eslint-plugin-testing-library` for the specified environment. |
22
24
 
23
25
  ## Example
24
26
 
@@ -30,6 +32,7 @@ export default [
30
32
  ...eslint.configure({ /* ... */ }),
31
33
  ...eslint.env.vitest({
32
34
  files: ["test/**/*.{js,ts}"],
35
+ testingLib: "react",
33
36
  rules: { /* ... */ },
34
37
  }),
35
38
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-xchange/linter-presets",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "Configuration presets for ESLint and StyleLint",
5
5
  "repository": {
6
6
  "url": "https://gitlab.open-xchange.com/fspd/npm-packages/linter-presets"
@@ -28,7 +28,7 @@
28
28
  "@babel/plugin-proposal-decorators": "7.24.7",
29
29
  "@eslint-community/eslint-plugin-eslint-comments": "4.3.0",
30
30
  "@eslint/compat": "1.1.1",
31
- "@eslint/js": "9.8.0",
31
+ "@eslint/js": "9.9.0",
32
32
  "@stylistic/eslint-plugin": "2.3.0",
33
33
  "@stylistic/eslint-plugin-migrate": "2.3.0",
34
34
  "@stylistic/stylelint-config": "2.0.0",
@@ -40,7 +40,7 @@
40
40
  "eslint-plugin-import": "2.29.1",
41
41
  "eslint-plugin-jest": "28.8.0",
42
42
  "eslint-plugin-jest-dom": "5.4.0",
43
- "eslint-plugin-jsdoc": "50.0.0",
43
+ "eslint-plugin-jsdoc": "50.2.2",
44
44
  "eslint-plugin-jsonc": "2.16.0",
45
45
  "eslint-plugin-jsx-a11y": "6.9.0",
46
46
  "eslint-plugin-jsx-expressions": "1.3.2",
@@ -51,7 +51,7 @@
51
51
  "eslint-plugin-react-hooks": "4.6.2",
52
52
  "eslint-plugin-react-hooks-static-deps": "1.0.7",
53
53
  "eslint-plugin-react-refresh": "0.4.9",
54
- "eslint-plugin-testing-library": "6.2.2",
54
+ "eslint-plugin-testing-library": "6.3.0",
55
55
  "eslint-plugin-vitest": "0.5.4",
56
56
  "eslint-plugin-yml": "1.14.0",
57
57
  "find-up": "7.0.0",
@@ -61,14 +61,14 @@
61
61
  "stylelint-config-standard-less": "3.0.1",
62
62
  "stylelint-config-standard-scss": "13.1.0",
63
63
  "stylelint-plugin-license-header": "1.0.3",
64
- "typescript-eslint": "8.0.1"
64
+ "typescript-eslint": "8.1.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/confusing-browser-globals": "1.0.3",
68
68
  "@types/eslint__js": "8.42.3",
69
- "@types/picomatch": "3.0.0",
70
- "@typescript-eslint/utils": "8.0.1",
71
- "eslint": "9.8.0",
69
+ "@types/picomatch": "3.0.1",
70
+ "@typescript-eslint/utils": "8.1.0",
71
+ "eslint": "9.9.0",
72
72
  "husky": "9.1.4",
73
73
  "jest": "29.7.0",
74
74
  "stylelint": "16.8.1",
@@ -0,0 +1,17 @@
1
+
2
+ /**
3
+ * @returns {string[]} A string array.
4
+ */
5
+ // eslint-disable-next-line @stylistic/space-before-function-paren
6
+ export function f () {
7
+ // eslint-disable-next-line @stylistic/quotes
8
+ const str1 = 'abc';
9
+ // eslint-disable-next-line @stylistic/semi
10
+ const str2 = str1
11
+ // eslint-disable-next-line @stylistic/indent
12
+ return [
13
+ str1,
14
+ // eslint-disable-next-line @stylistic/comma-dangle
15
+ str2
16
+ ];
17
+ }
@@ -0,0 +1,28 @@
1
+
2
+ /**
3
+ * @returns A string array.
4
+ */
5
+ // eslint-disable-next-line @stylistic/space-before-function-paren
6
+ export function f (): string[] {
7
+ // eslint-disable-next-line @stylistic/quotes
8
+ const str1 = 'abc';
9
+ // eslint-disable-next-line @stylistic/semi
10
+ const str2 = str1
11
+ // eslint-disable-next-line @stylistic/indent
12
+ return [
13
+ str1,
14
+ // eslint-disable-next-line @stylistic/comma-dangle
15
+ str2
16
+ ];
17
+ }
18
+
19
+ export interface I {
20
+ // eslint-disable-next-line @stylistic/member-delimiter-style
21
+ a: string,
22
+ // eslint-disable-next-line @stylistic/indent
23
+ b: number;
24
+ // eslint-disable-next-line @stylistic/quotes
25
+ ['*']: boolean;
26
+ // eslint-disable-next-line @stylistic/member-delimiter-style
27
+ c: boolean
28
+ }
@@ -0,0 +1,9 @@
1
+
2
+ describe("test", () => {
3
+ it("should work", () => {
4
+ // eslint-disable-next-line jest/prefer-to-be
5
+ expect(1).toEqual(1);
6
+ // eslint-disable-next-line jest/prefer-to-have-length
7
+ expect([].length).toBe(0);
8
+ });
9
+ });