Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Sep 25, 2020. It is now read-only.

Commit 40d9127

Browse files
armano2bradzacher
authored andcommitted
test(eslint-plugin): migrate validation tools to jest test cases (typescript-eslint#1403)
1 parent f7ad716 commit 40d9127

14 files changed

+214
-530
lines changed

azure-pipelines.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,10 @@ jobs:
3131
yarn lint
3232
displayName: 'Run linting'
3333
34-
- script: |
35-
yarn check:docs
36-
displayName: 'Validate documentation'
37-
3834
- script: |
3935
yarn check:spelling
4036
displayName: 'Validate documentation spelling'
4137
42-
- script: |
43-
yarn check:configs
44-
displayName: 'Validate plugin configs'
45-
4638
- script: |
4739
yarn test
4840
displayName: 'Run unit tests'

packages/eslint-plugin/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
"main": "dist/index.js",
3131
"scripts": {
3232
"build": "tsc -b tsconfig.build.json",
33-
"check:docs": "../../node_modules/.bin/ts-node --files --transpile-only ./tools/validate-docs/index.ts",
34-
"check:configs": "../../node_modules/.bin/ts-node --files --transpile-only ./tools/validate-configs/index.ts",
33+
"check:docs": "jest tests/docs.test.ts --runTestsByPath --silent --runInBand",
34+
"check:configs": "jest tests/configs.test.ts --runTestsByPath --silent --runInBand",
3535
"clean": "tsc -b tsconfig.build.json --clean",
3636
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
3737
"generate:configs": "../../node_modules/.bin/ts-node --files --transpile-only tools/generate-configs.ts",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import rules from '../src/rules';
2+
import plugin from '../src/index';
3+
4+
function entriesToObject<T = unknown>(value: [string, T][]): Record<string, T> {
5+
return value.reduce<Record<string, T>>((accum, [k, v]) => {
6+
accum[k] = v;
7+
return accum;
8+
}, {});
9+
}
10+
11+
const notDeprecatedRules = Object.entries(rules).filter(
12+
([, rule]) => !rule.meta.deprecated,
13+
);
14+
15+
function filterRules(values: Record<string, string>): [string, string][] {
16+
return Object.entries(values).filter(([name]) =>
17+
name.startsWith(RULE_NAME_PREFIX),
18+
);
19+
}
20+
21+
const RULE_NAME_PREFIX = '@typescript-eslint/';
22+
23+
describe('all.json config', () => {
24+
const configRules = filterRules(plugin.configs.all.rules);
25+
const ruleConfigs = notDeprecatedRules.map<[string, string]>(([name]) => [
26+
`${RULE_NAME_PREFIX}${name}`,
27+
'error',
28+
]);
29+
30+
it('contains all of the rules, excluding the deprecated ones', () => {
31+
expect(entriesToObject(ruleConfigs)).toEqual(entriesToObject(configRules));
32+
});
33+
});
34+
35+
describe('recommended.json config', () => {
36+
const configRules = filterRules(plugin.configs.recommended.rules);
37+
const ruleConfigs = notDeprecatedRules
38+
.filter(
39+
([, rule]) =>
40+
rule.meta.docs.recommended !== false &&
41+
rule.meta.docs.requiresTypeChecking !== true,
42+
)
43+
.map<[string, string]>(([name, rule]) => [
44+
`${RULE_NAME_PREFIX}${name}`,
45+
rule.meta.docs.recommended || 'off',
46+
]);
47+
48+
it("contains all recommended rules that don't require typechecking, excluding the deprecated ones", () => {
49+
expect(entriesToObject(ruleConfigs)).toEqual(entriesToObject(configRules));
50+
});
51+
});
52+
53+
describe('recommended-requiring-type-checking.json config', () => {
54+
const configRules = filterRules(
55+
plugin.configs['recommended-requiring-type-checking'].rules,
56+
);
57+
const ruleConfigs = notDeprecatedRules
58+
.filter(
59+
([, rule]) =>
60+
rule.meta.docs.recommended !== false &&
61+
rule.meta.docs.requiresTypeChecking === true,
62+
)
63+
.map<[string, string]>(([name, rule]) => [
64+
`${RULE_NAME_PREFIX}${name}`,
65+
rule.meta.docs.recommended || 'off',
66+
]);
67+
68+
it('contains all recommended rules that require type checking, excluding the deprecated ones', () => {
69+
expect(entriesToObject(ruleConfigs)).toEqual(entriesToObject(configRules));
70+
});
71+
});

packages/eslint-plugin/tests/configs/all.test.ts

Lines changed: 0 additions & 42 deletions
This file was deleted.
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
import marked from 'marked';
5+
import rules from '../src/rules';
6+
7+
const docsRoot = path.resolve(__dirname, '../docs/rules');
8+
const rulesData = Object.entries(rules);
9+
10+
function createRuleLink(ruleName: string): string {
11+
return `[\`@typescript-eslint/${ruleName}\`](./docs/rules/${ruleName}.md)`;
12+
}
13+
14+
function parseReadme(): marked.Tokens.Table {
15+
const readmeRaw = fs.readFileSync(
16+
path.resolve(__dirname, '../README.md'),
17+
'utf8',
18+
);
19+
const readme = marked.lexer(readmeRaw, {
20+
gfm: true,
21+
silent: false,
22+
});
23+
24+
// find the table
25+
const rulesTable = readme.find(
26+
(token): token is marked.Tokens.Table => token.type === 'table',
27+
);
28+
if (!rulesTable) {
29+
throw Error('Could not find the rules table in README.md');
30+
}
31+
32+
return rulesTable;
33+
}
34+
35+
describe('Validating rule docs', () => {
36+
it('All rules must have a corresponding rule doc', () => {
37+
const files = fs.readdirSync(docsRoot);
38+
const ruleFiles = Object.keys(rules)
39+
.map(rule => `${rule}.md`)
40+
.sort();
41+
42+
expect(files.sort()).toEqual(ruleFiles);
43+
});
44+
45+
for (const [ruleName, rule] of rulesData) {
46+
const filePath = path.join(docsRoot, `${ruleName}.md`);
47+
it(`Description of ${ruleName}.md must match`, () => {
48+
// validate if description of rule is same as in docs
49+
const file = fs.readFileSync(filePath, 'utf-8');
50+
const tokens = marked.lexer(file, {
51+
gfm: true,
52+
silent: false,
53+
});
54+
55+
// Rule title not found.
56+
// Rule title does not match the rule metadata.
57+
expect(tokens[0]).toEqual({
58+
type: 'heading',
59+
depth: 1,
60+
text: `${rule.meta.docs.description} (\`${ruleName}\`)`,
61+
});
62+
});
63+
}
64+
});
65+
66+
describe('Validating rule metadata', () => {
67+
for (const [ruleName, rule] of rulesData) {
68+
describe(`${ruleName}`, () => {
69+
it('`name` field in rule must match the filename', () => {
70+
// validate if rule name is same as url
71+
// there is no way to access this field but its used only in generation of docs url
72+
expect(
73+
rule.meta.docs.url.endsWith(`rules/${ruleName}.md`),
74+
).toBeTruthy();
75+
});
76+
77+
it('`requiresTypeChecking` should be set if the rule uses type information', () => {
78+
// quick-and-dirty check to see if it uses parserServices
79+
// not perfect but should be good enough
80+
const ruleFileContents = fs.readFileSync(
81+
path.resolve(__dirname, `../src/rules/${ruleName}.ts`),
82+
);
83+
84+
expect(ruleFileContents.includes('getParserServices')).toEqual(
85+
rule.meta.docs.requiresTypeChecking ?? false,
86+
);
87+
});
88+
});
89+
}
90+
});
91+
92+
describe('Validating README.md', () => {
93+
const rulesTable = parseReadme().cells;
94+
const notDeprecated = rulesData.filter(
95+
([, rule]) => rule.meta.deprecated !== true,
96+
);
97+
98+
it('All non-deprecated rules should have a row in the table, and the table should be ordered alphabetically', () => {
99+
const ruleNames = notDeprecated
100+
.map(([ruleName]) => ruleName)
101+
.sort()
102+
.map(createRuleLink);
103+
104+
expect(rulesTable.map(row => row[0])).toStrictEqual(ruleNames);
105+
});
106+
107+
for (const [ruleName, rule] of notDeprecated) {
108+
describe(`Checking rule ${ruleName}`, () => {
109+
const ruleRow =
110+
rulesTable.find(row => row[0].includes(`/${ruleName}.md`)) ?? [];
111+
112+
it('Link column should be correct', () => {
113+
expect(ruleRow[0]).toEqual(createRuleLink(ruleName));
114+
});
115+
116+
it('Description column should be correct', () => {
117+
expect(ruleRow[1]).toEqual(rule.meta.docs.description);
118+
});
119+
120+
it('Recommended column should be correct', () => {
121+
expect(ruleRow[2]).toEqual(
122+
rule.meta.docs.recommended ? ':heavy_check_mark:' : '',
123+
);
124+
});
125+
126+
it('Fixable column should be correct', () => {
127+
expect(ruleRow[3]).toEqual(
128+
rule.meta.fixable !== undefined ? ':wrench:' : '',
129+
);
130+
});
131+
132+
it('Requiring type information column should be correct', () => {
133+
expect(ruleRow[4]).toEqual(
134+
rule.meta.docs.requiresTypeChecking === true
135+
? ':thought_balloon:'
136+
: '',
137+
);
138+
});
139+
});
140+
}
141+
});

packages/eslint-plugin/tools/validate-configs/checkConfigAll.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

packages/eslint-plugin/tools/validate-configs/checkConfigRecommended.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)