/
index.js
132 lines (112 loc) · 4.99 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* eslint-env mocha */
'use strict';
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const plugin = require('..');
const ruleFiles = fs.readdirSync(path.resolve(__dirname, '../lib/rules/'))
.map((f) => path.basename(f, '.js'));
describe('all rule files should be exported by the plugin', () => {
ruleFiles.forEach((ruleName) => {
it(`should export ${ruleName}`, () => {
assert.equal(
plugin.rules[ruleName],
require(path.join('../lib/rules', ruleName)) // eslint-disable-line global-require, import/no-dynamic-require
);
});
});
});
describe('rule documentation files have the correct content', () => {
const MESSAGES = {
fixable: '🔧 This rule is automatically fixable using the `--fix` [flag](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix) on the command line.',
hasSuggestions: '💡 This rule provides editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).',
};
ruleFiles.forEach((ruleFile) => {
const ruleName = path.basename(ruleFile, '.js');
const rule = plugin.rules[ruleName];
const documentPath = path.join('docs/rules', `${ruleName}.md`);
const documentContents = fs.readFileSync(documentPath, 'utf8');
const documentLines = documentContents.split('\n');
// Decide which notices should be shown at the top of the doc.
const expectedNotices = [];
const unexpectedNotices = [];
if (rule.meta.fixable) {
expectedNotices.push('fixable');
} else {
unexpectedNotices.push('fixable');
}
if (rule.meta.hasSuggestions) {
expectedNotices.push('hasSuggestions');
} else {
unexpectedNotices.push('hasSuggestions');
}
// Ensure that expected notices are present in the correct order.
let currentLineNumber = 1;
expectedNotices.forEach((expectedNotice) => {
assert.strictEqual(documentLines[currentLineNumber], '', `${ruleName} includes blank line ahead of ${expectedNotice} notice`);
assert.strictEqual(documentLines[currentLineNumber + 1], MESSAGES[expectedNotice], `${ruleName} includes ${expectedNotice} notice`);
currentLineNumber += 2;
});
// Ensure that unexpected notices are not present.
unexpectedNotices.forEach((unexpectedNotice) => {
assert.ok(!documentContents.includes(MESSAGES[unexpectedNotice]), `${ruleName} does not include unexpected ${unexpectedNotice} notice`);
});
});
});
describe('deprecated rules', () => {
it('marks all deprecated rules as deprecated', () => {
ruleFiles.forEach((ruleName) => {
const inDeprecatedRules = Boolean(plugin.deprecatedRules[ruleName]);
const isDeprecated = plugin.rules[ruleName].meta.deprecated;
if (inDeprecatedRules) {
assert(isDeprecated, `${ruleName} metadata should mark it as deprecated`);
} else {
assert(!isDeprecated, `${ruleName} metadata should not mark it as deprecated`);
}
});
});
});
describe('configurations', () => {
it('should export a ‘recommended’ configuration', () => {
const configName = 'recommended';
assert(plugin.configs[configName]);
Object.keys(plugin.configs[configName].rules).forEach((ruleName) => {
assert.ok(ruleName.startsWith('react/'));
const subRuleName = ruleName.slice('react/'.length);
assert(plugin.rules[subRuleName]);
});
ruleFiles.forEach((ruleName) => {
const inRecommendedConfig = !!plugin.configs[configName].rules[`react/${ruleName}`];
const isRecommended = plugin.rules[ruleName].meta.docs[configName];
if (inRecommendedConfig) {
assert(isRecommended, `${ruleName} metadata should mark it as recommended`);
} else {
assert(!isRecommended, `${ruleName} metadata should not mark it as recommended`);
}
});
});
it('should export an ‘all’ configuration', () => {
const configName = 'all';
assert(plugin.configs[configName]);
Object.keys(plugin.configs[configName].rules).forEach((ruleName) => {
assert.ok(ruleName.startsWith('react/'));
assert.equal(plugin.configs[configName].rules[ruleName], 2);
});
ruleFiles.forEach((ruleName) => {
const inDeprecatedRules = Boolean(plugin.deprecatedRules[ruleName]);
const inConfig = typeof plugin.configs[configName].rules[`react/${ruleName}`] !== 'undefined';
assert(inDeprecatedRules ^ inConfig); // eslint-disable-line no-bitwise
});
});
it('should export a \'jsx-runtime\' configuration', () => {
const configName = 'jsx-runtime';
assert(plugin.configs[configName]);
Object.keys(plugin.configs[configName].rules).forEach((ruleName) => {
assert.ok(ruleName.startsWith('react/'));
assert.equal(plugin.configs[configName].rules[ruleName], 0);
const inDeprecatedRules = Boolean(plugin.deprecatedRules[ruleName]);
const inConfig = typeof plugin.configs[configName].rules[ruleName] !== 'undefined';
assert(inDeprecatedRules ^ inConfig); // eslint-disable-line no-bitwise
});
});
});