]> git.proxmox.com Git - pve-eslint.git/blob - eslint/tests/lib/init/autoconfig.js
first commit
[pve-eslint.git] / eslint / tests / lib / init / autoconfig.js
1 /**
2 * @fileoverview Used for creating a suggested configuration based on project code.
3 * @author Ian VanSchooten
4 */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const assert = require("chai").assert,
13 autoconfig = require("../../../lib/init/autoconfig"),
14 sourceCodeUtils = require("../../../lib/init/source-code-utils"),
15 baseDefaultOptions = require("../../../conf/default-cli-options");
16
17 const defaultOptions = Object.assign({}, baseDefaultOptions, { cwd: process.cwd() });
18
19 //------------------------------------------------------------------------------
20 // Data
21 //------------------------------------------------------------------------------
22
23 const SOURCE_CODE_FIXTURE_FILENAME = "./tests/fixtures/autoconfig/source.js";
24 const CONFIG_COMMENTS_FILENAME = "./tests/fixtures/autoconfig/source-with-comments.js";
25 const SEVERITY = 2;
26
27 //------------------------------------------------------------------------------
28 // Tests
29 //------------------------------------------------------------------------------
30
31 const rulesConfig = {
32 semi: [SEVERITY, [SEVERITY, "always"], [SEVERITY, "never"]],
33 "semi-spacing": [SEVERITY,
34 [SEVERITY, { before: true, after: true }],
35 [SEVERITY, { before: true, after: false }],
36 [SEVERITY, { before: false, after: true }],
37 [SEVERITY, { before: false, after: false }]
38 ],
39 quotes: [SEVERITY,
40 [SEVERITY, "single"],
41 [SEVERITY, "double"],
42 [SEVERITY, "backtick"],
43 [SEVERITY, "single", "avoid-escape"],
44 [SEVERITY, "double", "avoid-escape"],
45 [SEVERITY, "backtick", "avoid-escape"]]
46 };
47
48 const errorRulesConfig = {
49 "no-unused-vars": [SEVERITY],
50 "semi-spacing": [SEVERITY,
51 [SEVERITY, { before: true, after: true }],
52 [SEVERITY, { before: true, after: false }],
53 [SEVERITY, { before: false, after: true }],
54 [SEVERITY, { before: false, after: false }]
55 ]
56 };
57
58 describe("autoconfig", () => {
59
60 describe("Registry", () => {
61
62 it("should set up a registry for rules in a provided rulesConfig", () => {
63 const expectedRules = Object.keys(rulesConfig);
64 const registry = new autoconfig.Registry(rulesConfig);
65
66 assert.strictEqual(Object.keys(registry.rules).length, 3);
67 assert.sameMembers(Object.keys(registry.rules), expectedRules);
68 assert.isArray(registry.rules.semi);
69 assert.isArray(registry.rules["semi-spacing"]);
70 assert.isArray(registry.rules.quotes);
71 assert.lengthOf(registry.rules.semi, 3);
72 assert.lengthOf(registry.rules["semi-spacing"], 5);
73 assert.lengthOf(registry.rules.quotes, 7);
74 });
75
76 it("should not have any rules if constructed without a config argument", () => {
77 const registry = new autoconfig.Registry();
78
79 assert.isObject(registry.rules);
80 assert.lengthOf(Object.keys(registry.rules), 0);
81 });
82
83 it("should create registryItems for each rule with the proper keys", () => {
84 const registry = new autoconfig.Registry(rulesConfig);
85
86 assert.isObject(registry.rules.semi[0]);
87 assert.isObject(registry.rules["semi-spacing"][0]);
88 assert.isObject(registry.rules.quotes[0]);
89 assert.property(registry.rules.semi[0], "config");
90 assert.property(registry.rules.semi[0], "specificity");
91 assert.property(registry.rules.semi[0], "errorCount");
92 });
93
94 it("should populate the config property correctly", () => {
95 const registry = new autoconfig.Registry(rulesConfig);
96
97 assert.strictEqual(registry.rules.quotes[0].config, SEVERITY);
98 assert.deepStrictEqual(registry.rules.quotes[1].config, [SEVERITY, "single"]);
99 assert.deepStrictEqual(registry.rules.quotes[2].config, [SEVERITY, "double"]);
100 assert.deepStrictEqual(registry.rules.quotes[3].config, [SEVERITY, "backtick"]);
101 assert.deepStrictEqual(registry.rules.quotes[4].config, [SEVERITY, "single", "avoid-escape"]);
102 assert.deepStrictEqual(registry.rules.quotes[5].config, [SEVERITY, "double", "avoid-escape"]);
103 assert.deepStrictEqual(registry.rules.quotes[6].config, [SEVERITY, "backtick", "avoid-escape"]);
104 });
105
106 it("should assign the correct specificity", () => {
107 const registry = new autoconfig.Registry(rulesConfig);
108
109 assert.strictEqual(registry.rules.quotes[0].specificity, 1);
110 assert.strictEqual(registry.rules.quotes[1].specificity, 2);
111 assert.strictEqual(registry.rules.quotes[6].specificity, 3);
112 });
113
114 it("should initially leave the errorCount as undefined", () => {
115 const registry = new autoconfig.Registry(rulesConfig);
116
117 assert.isUndefined(registry.rules.quotes[0].errorCount);
118 assert.isUndefined(registry.rules.quotes[1].errorCount);
119 assert.isUndefined(registry.rules.quotes[6].errorCount);
120 });
121
122 describe("populateFromCoreRules()", () => {
123
124 it("should add core rules to registry", () => {
125 const registry = new autoconfig.Registry();
126
127 registry.populateFromCoreRules();
128 const finalRuleCount = Object.keys(registry.rules).length;
129
130 assert(finalRuleCount > 0);
131 assert.include(Object.keys(registry.rules), "eqeqeq");
132 });
133
134 it("should not add duplicate rules", () => {
135 const registry = new autoconfig.Registry(rulesConfig);
136
137 registry.populateFromCoreRules();
138 const semiCount = Object.keys(registry.rules).filter(ruleId => ruleId === "semi").length;
139
140 assert.strictEqual(semiCount, 1);
141 });
142 });
143
144 describe("buildRuleSets()", () => {
145 let ruleSets;
146
147 beforeEach(() => {
148 const registry = new autoconfig.Registry(rulesConfig);
149
150 ruleSets = registry.buildRuleSets();
151 });
152
153 it("should create an array of rule configuration sets", () => {
154 assert.isArray(ruleSets);
155 });
156
157 it("should include configs for each rule (at least for the first set)", () => {
158 assert.sameMembers(Object.keys(ruleSets[0]), ["semi", "semi-spacing", "quotes"]);
159 });
160
161 it("should create the first set from default rule configs (severity only)", () => {
162 assert.deepStrictEqual(ruleSets[0], { semi: SEVERITY, "semi-spacing": SEVERITY, quotes: SEVERITY });
163 });
164
165 it("should create as many ruleSets as the highest number of configs in a rule", () => {
166
167 // `quotes` has 7 possible configurations
168 assert.lengthOf(ruleSets, 7);
169 });
170 });
171
172 describe("lintSourceCode()", () => {
173 let registry;
174
175 beforeEach(() => {
176 const config = { ignore: false };
177 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
178
179 registry = new autoconfig.Registry(rulesConfig);
180 registry = registry.lintSourceCode(sourceCode, defaultOptions);
181 });
182
183 it("should populate the errorCount of all registryItems", () => {
184 const expectedRules = ["semi", "semi-spacing", "quotes"];
185
186 assert.sameMembers(Object.keys(registry.rules), expectedRules);
187 expectedRules.forEach(ruleId => {
188 assert(registry.rules[ruleId].length > 0);
189 registry.rules[ruleId].forEach(conf => {
190 assert.isNumber(conf.errorCount);
191 });
192 });
193 });
194
195 it("should correctly set the error count of configurations", () => {
196 assert.strictEqual(registry.rules.semi[0].config, SEVERITY);
197 assert.strictEqual(registry.rules.semi[0].errorCount, 0);
198 assert.deepStrictEqual(registry.rules.semi[2].config, [SEVERITY, "never"]);
199 assert.strictEqual(registry.rules.semi[2].errorCount, 3);
200 });
201
202 it("should respect inline eslint config comments (and not crash when they make linting errors)", () => {
203 const config = { ignore: false };
204 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(CONFIG_COMMENTS_FILENAME, config);
205 const expectedRegistry = [
206 { config: 2, specificity: 1, errorCount: 3 },
207 { config: [2, "always"], specificity: 2, errorCount: 3 },
208 { config: [2, "never"], specificity: 2, errorCount: 3 }
209 ];
210
211 registry = new autoconfig.Registry(rulesConfig);
212 registry = registry.lintSourceCode(sourceCode, defaultOptions);
213
214 assert.deepStrictEqual(registry.rules.semi, expectedRegistry);
215 });
216 });
217
218 describe("stripFailingConfigs()", () => {
219 let registry;
220
221 beforeEach(() => {
222 const config = { ignore: false };
223 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
224
225 registry = new autoconfig.Registry(rulesConfig);
226 registry = registry.lintSourceCode(sourceCode, defaultOptions);
227 registry = registry.stripFailingConfigs();
228 });
229
230 it("should remove all registryItems with a non-zero errorCount", () => {
231 assert.lengthOf(registry.rules.semi, 2);
232 assert.lengthOf(registry.rules["semi-spacing"], 3);
233 assert.lengthOf(registry.rules.quotes, 1);
234 registry.rules.semi.forEach(registryItem => {
235 assert.strictEqual(registryItem.errorCount, 0);
236 });
237 registry.rules["semi-spacing"].forEach(registryItem => {
238 assert.strictEqual(registryItem.errorCount, 0);
239 });
240 registry.rules.quotes.forEach(registryItem => {
241 assert.strictEqual(registryItem.errorCount, 0);
242 });
243 });
244 });
245
246 describe("getFailingRulesRegistry()", () => {
247 let failingRegistry;
248
249 beforeEach(() => {
250 const config = { ignore: false };
251 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
252 let registry = new autoconfig.Registry(errorRulesConfig);
253
254 registry = registry.lintSourceCode(sourceCode, defaultOptions);
255 failingRegistry = registry.getFailingRulesRegistry();
256 });
257
258 it("should return a registry with no registryItems with an errorCount of zero", () => {
259 const failingRules = Object.keys(failingRegistry.rules);
260
261 assert.deepStrictEqual(failingRules, ["no-unused-vars"]);
262 assert.lengthOf(failingRegistry.rules["no-unused-vars"], 1);
263 assert(failingRegistry.rules["no-unused-vars"][0].errorCount > 0);
264 });
265 });
266
267 describe("createConfig()", () => {
268 let createdConfig;
269
270 beforeEach(() => {
271 const config = { ignore: false };
272 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
273 let registry = new autoconfig.Registry(rulesConfig);
274
275 registry = registry.lintSourceCode(sourceCode, defaultOptions);
276 registry = registry.stripFailingConfigs();
277 createdConfig = registry.createConfig();
278 });
279
280 it("should create a config with a rules property", () => {
281 assert.property(createdConfig, "rules");
282 });
283
284 it("should add rules which have only one registryItem to the config", () => {
285 const configuredRules = Object.keys(createdConfig.rules);
286
287 assert.deepStrictEqual(configuredRules, ["quotes"]);
288 });
289
290 it("should set the configuration of the rule to the registryItem's `config` value", () => {
291 assert.deepStrictEqual(createdConfig.rules.quotes, [2, "double", "avoid-escape"]);
292 });
293
294 it("should not care how many errors the config has", () => {
295 const config = { ignore: false };
296 const sourceCode = sourceCodeUtils.getSourceCodeOfFiles(SOURCE_CODE_FIXTURE_FILENAME, config);
297 let registry = new autoconfig.Registry(errorRulesConfig);
298
299 registry = registry.lintSourceCode(sourceCode, defaultOptions);
300 const failingRegistry = registry.getFailingRulesRegistry();
301
302 createdConfig = failingRegistry.createConfig();
303 const configuredRules = Object.keys(createdConfig.rules);
304
305 assert.deepStrictEqual(configuredRules, ["no-unused-vars"]);
306 });
307 });
308
309 describe("filterBySpecificity()", () => {
310 let registry;
311
312 beforeEach(() => {
313 registry = new autoconfig.Registry(rulesConfig);
314 });
315
316 it("should return a registry where all configs have a desired specificity", () => {
317 const filteredRegistry1 = registry.filterBySpecificity(1);
318 const filteredRegistry2 = registry.filterBySpecificity(2);
319 const filteredRegistry3 = registry.filterBySpecificity(3);
320
321 assert.lengthOf(filteredRegistry1.rules.semi, 1);
322 assert.lengthOf(filteredRegistry1.rules["semi-spacing"], 1);
323 assert.lengthOf(filteredRegistry1.rules.quotes, 1);
324 assert.lengthOf(filteredRegistry2.rules.semi, 2);
325 assert.lengthOf(filteredRegistry2.rules["semi-spacing"], 4);
326 assert.lengthOf(filteredRegistry2.rules.quotes, 3);
327 assert.lengthOf(filteredRegistry3.rules.quotes, 3);
328 });
329 });
330 });
331 });