UNPKG

5.71 kBPlain TextView Raw
1import { TSESLint } from '@typescript-eslint/experimental-utils';
2import * as parser from '@typescript-eslint/parser';
3import { readFileSync } from 'fs';
4import rule, { Options } from '../src/rules/config';
5
6const ruleTester = new TSESLint.RuleTester({
7 parserOptions: {
8 ecmaVersion: 6,
9 sourceType: 'module',
10 ecmaFeatures: {},
11 /**
12 * Project is needed to generate the parserServices
13 * within @typescript-eslint/parser
14 */
15 project: './tests/fixture-project/tsconfig.json',
16 warnOnUnsupportedTypeScriptVersion: false,
17 },
18 parser: require.resolve('@typescript-eslint/parser'),
19});
20
21/**
22 * Inline rules should be supported
23 */
24const tslintRulesConfig: Options = [
25 {
26 rules: {
27 semicolon: [true, 'always'],
28 },
29 },
30];
31
32/**
33 * Custom rules directories should be supported
34 */
35const tslintRulesDirectoryConfig: Options = [
36 {
37 rulesDirectory: ['./tests/test-tslint-rules-directory'],
38 rules: {
39 'always-fail': {
40 severity: 'error',
41 },
42 },
43 },
44];
45
46ruleTester.run('tslint/config', rule, {
47 valid: [
48 {
49 code: 'var foo = true;',
50 options: tslintRulesConfig,
51 filename: './tests/fixture-project/1.ts',
52 },
53 {
54 filename: './tests/test-project/file-spec.ts',
55 code: readFileSync('./tests/test-project/file-spec.ts', 'utf8').replace(
56 /\n/g,
57 ' ',
58 ),
59 parserOptions: {
60 project: `${__dirname}/test-project/tsconfig.json`,
61 },
62 options: tslintRulesConfig,
63 },
64 {
65 code: 'throw "should be ok because rule is not loaded";',
66 options: tslintRulesConfig,
67 filename: './tests/fixture-project/2.ts',
68 },
69 ],
70
71 invalid: [
72 {
73 options: [{ lintFile: './tests/test-project/tslint.json' }],
74 code: 'throw "err" // no-string-throw',
75 output: 'throw new Error("err") // no-string-throw',
76 filename: './tests/fixture-project/3.ts',
77 errors: [
78 {
79 messageId: 'failure',
80 data: {
81 message:
82 'Throwing plain strings (not instances of Error) gives no stack traces',
83 ruleName: 'no-string-throw',
84 },
85 },
86 ],
87 },
88 {
89 code: 'var foo = true // semicolon',
90 options: tslintRulesConfig,
91 output: 'var foo = true; // semicolon',
92 filename: './tests/fixture-project/4.ts',
93 errors: [
94 {
95 messageId: 'failure',
96 data: {
97 message: 'Missing semicolon',
98 ruleName: 'semicolon',
99 },
100 line: 1,
101 column: 15,
102 },
103 ],
104 },
105 {
106 code: 'var foo = true // fail',
107 options: tslintRulesDirectoryConfig,
108 output: 'var foo = true // fail',
109 filename: './tests/fixture-project/5.ts',
110 errors: [
111 {
112 messageId: 'failure',
113 data: {
114 message: 'failure',
115 ruleName: 'always-fail',
116 },
117 line: 1,
118 column: 1,
119 },
120 ],
121 },
122 {
123 filename: './tests/test-project/source.ts',
124 code: readFileSync('./tests/test-project/source.ts', 'utf8').replace(
125 /\n/g,
126 ' ',
127 ),
128 parserOptions: {
129 project: `${__dirname}/test-project/tsconfig.json`,
130 },
131 options: [
132 {
133 rulesDirectory: [
134 `${__dirname}/../../../node_modules/tslint/lib/rules`,
135 ],
136 rules: { 'restrict-plus-operands': true },
137 },
138 ],
139 errors: [
140 {
141 messageId: 'failure',
142 data: {
143 message:
144 'Operands of \'+\' operation must either be both strings or both numbers or both bigints, but found 1 + "2". Consider using template literals.',
145 ruleName: 'restrict-plus-operands',
146 },
147 },
148 ],
149 },
150 ],
151});
152
153describe('tslint/error', () => {
154 function testOutput(code: string, config: TSESLint.Linter.Config): void {
155 const linter = new TSESLint.Linter();
156 linter.defineRule('tslint/config', rule);
157 linter.defineParser('@typescript-eslint/parser', parser);
158
159 expect(() => linter.verify(code, config)).toThrow(
160 'You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.',
161 );
162 }
163
164 it('should error on missing project', () => {
165 testOutput('foo;', {
166 rules: {
167 'tslint/config': [2, tslintRulesConfig],
168 },
169 parser: '@typescript-eslint/parser',
170 });
171 });
172
173 it('should error on default parser', () => {
174 testOutput('foo;', {
175 parserOptions: {
176 project: `${__dirname}/test-project/tsconfig.json`,
177 },
178 rules: {
179 'tslint/config': [2, tslintRulesConfig],
180 },
181 });
182 });
183
184 it('should not crash if there are no tslint rules specified', () => {
185 const linter = new TSESLint.Linter();
186 jest.spyOn(console, 'warn').mockImplementation();
187 linter.defineRule('tslint/config', rule);
188 linter.defineParser('@typescript-eslint/parser', parser);
189 expect(() =>
190 linter.verify(
191 'foo;',
192 {
193 parserOptions: {
194 project: `${__dirname}/test-project/tsconfig.json`,
195 },
196 rules: {
197 'tslint/config': [2, {}],
198 },
199 parser: '@typescript-eslint/parser',
200 },
201 `${__dirname}/test-project/extra.ts`,
202 ),
203 ).not.toThrow();
204
205 expect(console.warn).toHaveBeenCalledWith(
206 expect.stringContaining(
207 `Tried to lint ${__dirname}/test-project/extra.ts but found no valid, enabled rules for this file type and file path in the resolved configuration.`,
208 ),
209 );
210 jest.resetAllMocks();
211 });
212});