Skip to content

Commit f1a9abb

Browse files
committed
test: correct unit tests and e2e tests for language service (#1579)
1 parent b29f743 commit f1a9abb

File tree

11 files changed

+81
-210
lines changed

11 files changed

+81
-210
lines changed

e2e/__tests__/__snapshots__/diagnostics.test.ts.snap

+3-153
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`With diagnostics throw first throw should fail using template "default" 1`] = `
3+
exports[`With diagnostics throw should fail using template "default" 1`] = `
44
× jest
55
↳ exit code: 1
66
===[ STDOUT ]===================================================================
@@ -27,7 +27,7 @@ exports[`With diagnostics throw first throw should fail using template "default"
2727
================================================================================
2828
`;
2929

30-
exports[`With diagnostics throw first throw should fail using template "with-babel-7" 1`] = `
30+
exports[`With diagnostics throw should fail using template "with-babel-7" 1`] = `
3131
× jest
3232
↳ exit code: 1
3333
===[ STDOUT ]===================================================================
@@ -54,7 +54,7 @@ exports[`With diagnostics throw first throw should fail using template "with-bab
5454
================================================================================
5555
`;
5656

57-
exports[`With diagnostics throw first throw should fail using template "with-babel-7-string-config" 1`] = `
57+
exports[`With diagnostics throw should fail using template "with-babel-7-string-config" 1`] = `
5858
× jest
5959
↳ exit code: 1
6060
===[ STDOUT ]===================================================================
@@ -81,156 +81,6 @@ exports[`With diagnostics throw first throw should fail using template "with-bab
8181
================================================================================
8282
`;
8383

84-
exports[`With diagnostics throw then fail when code has changed to invalid base on cache of the previous run should fail using template "default" 1`] = `
85-
× jest
86-
↳ exit code: 1
87-
===[ STDOUT ]===================================================================
88-
89-
===[ STDERR ]===================================================================
90-
FAIL ./main.spec.ts
91-
× foo is 42
92-
93-
● foo is 42
94-
95-
expect(received).toBe(expected) // Object.is equality
96-
97-
Expected: 42
98-
Received: 43
99-
100-
4 |
101-
5 | test('foo is 42', () => {
102-
> 6 | expect(foo).toBe(42);
103-
| ^
104-
7 | });
105-
8 |
106-
107-
at Object.<anonymous> (main.spec.ts:6:15)
108-
109-
Test Suites: 1 failed, 1 total
110-
Tests: 1 failed, 1 total
111-
Snapshots: 0 total
112-
Time: XXs
113-
Ran all test suites.
114-
================================================================================
115-
`;
116-
117-
exports[`With diagnostics throw then fail when code has changed to invalid base on cache of the previous run should fail using template "with-babel-7" 1`] = `
118-
× jest
119-
↳ exit code: 1
120-
===[ STDOUT ]===================================================================
121-
122-
===[ STDERR ]===================================================================
123-
FAIL ./main.spec.ts
124-
× foo is 42
125-
126-
● foo is 42
127-
128-
expect(received).toBe(expected) // Object.is equality
129-
130-
Expected: 42
131-
Received: 43
132-
133-
4 |
134-
5 | test('foo is 42', () => {
135-
> 6 | expect(foo).toBe(42);
136-
| ^
137-
7 | });
138-
8 |
139-
140-
at Object.<anonymous> (main.spec.ts:6:15)
141-
142-
Test Suites: 1 failed, 1 total
143-
Tests: 1 failed, 1 total
144-
Snapshots: 0 total
145-
Time: XXs
146-
Ran all test suites.
147-
================================================================================
148-
`;
149-
150-
exports[`With diagnostics throw then fail when code has changed to invalid base on cache of the previous run should fail using template "with-babel-7-string-config" 1`] = `
151-
× jest
152-
↳ exit code: 1
153-
===[ STDOUT ]===================================================================
154-
155-
===[ STDERR ]===================================================================
156-
FAIL ./main.spec.ts
157-
× foo is 42
158-
159-
● foo is 42
160-
161-
expect(received).toBe(expected) // Object.is equality
162-
163-
Expected: 42
164-
Received: 43
165-
166-
4 |
167-
5 | test('foo is 42', () => {
168-
> 6 | expect(foo).toBe(42);
169-
| ^
170-
7 | });
171-
8 |
172-
173-
at Object.<anonymous> (main.spec.ts:6:15)
174-
175-
Test Suites: 1 failed, 1 total
176-
Tests: 1 failed, 1 total
177-
Snapshots: 0 total
178-
Time: XXs
179-
Ran all test suites.
180-
================================================================================
181-
`;
182-
183-
exports[`With diagnostics throw then pass when type has changed to valid base on cache of the previous run should pass using template "default" 1`] = `
184-
√ jest
185-
↳ exit code: 0
186-
===[ STDOUT ]===================================================================
187-
188-
===[ STDERR ]===================================================================
189-
PASS ./main.spec.ts
190-
√ foo is 42
191-
192-
Test Suites: 1 passed, 1 total
193-
Tests: 1 passed, 1 total
194-
Snapshots: 0 total
195-
Time: XXs
196-
Ran all test suites.
197-
================================================================================
198-
`;
199-
200-
exports[`With diagnostics throw then pass when type has changed to valid base on cache of the previous run should pass using template "with-babel-7" 1`] = `
201-
√ jest
202-
↳ exit code: 0
203-
===[ STDOUT ]===================================================================
204-
205-
===[ STDERR ]===================================================================
206-
PASS ./main.spec.ts
207-
√ foo is 42
208-
209-
Test Suites: 1 passed, 1 total
210-
Tests: 1 passed, 1 total
211-
Snapshots: 0 total
212-
Time: XXs
213-
Ran all test suites.
214-
================================================================================
215-
`;
216-
217-
exports[`With diagnostics throw then pass when type has changed to valid base on cache of the previous run should pass using template "with-babel-7-string-config" 1`] = `
218-
√ jest
219-
↳ exit code: 0
220-
===[ STDOUT ]===================================================================
221-
222-
===[ STDERR ]===================================================================
223-
PASS ./main.spec.ts
224-
√ foo is 42
225-
226-
Test Suites: 1 passed, 1 total
227-
Tests: 1 passed, 1 total
228-
Snapshots: 0 total
229-
Time: XXs
230-
Ran all test suites.
231-
================================================================================
232-
`;
233-
23484
exports[`With diagnostics warn only should pass using template "default" 1`] = `
23585
√ jest --no-cache
23686
↳ exit code: 0

e2e/__tests__/diagnostics.test.ts

+5-46
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,14 @@
1-
import { writeFileSync } from 'fs'
2-
import { join } from 'path'
3-
41
import { allValidPackageSets } from '../__helpers__/templates'
52
import { configureTestCase } from '../__helpers__/test-case'
63

74
describe('With diagnostics throw', () => {
85
const testCase = configureTestCase('diagnostics/throw')
96

10-
describe('first throw', () => {
11-
testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
12-
it(testLabel, () => {
13-
const result = runTest()
14-
expect(result.status).toBe(1)
15-
expect(result).toMatchSnapshot()
16-
})
17-
})
18-
})
19-
20-
describe('then pass when type has changed to valid base on cache of the previous run', () => {
21-
beforeAll(() => {
22-
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number }`)
23-
})
24-
25-
afterAll(() => {
26-
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`)
27-
})
28-
29-
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
30-
it(testLabel, () => {
31-
const result = runTest()
32-
expect(result.status).toBe(0)
33-
expect(result).toMatchSnapshot()
34-
})
35-
})
36-
})
37-
38-
describe('then fail when code has changed to invalid base on cache of the previous run', () => {
39-
beforeAll(() => {
40-
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 43\nexport type Thing = { a: number }`)
41-
})
42-
43-
afterAll(() => {
44-
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`)
45-
})
46-
47-
testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
48-
it(testLabel, () => {
49-
const result = runTest()
50-
expect(result.status).toBe(1)
51-
expect(result).toMatchSnapshot()
52-
})
7+
testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
8+
it(testLabel, () => {
9+
const result = runTest()
10+
expect(result.status).toBe(1)
11+
expect(result).toMatchSnapshot()
5312
})
5413
})
5514
})

src/__helpers__/fakers.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@ export function makeCompiler({
6868
pretty: false,
6969
}
7070
const testRegex = ['^.+\\.[tj]sx?$']
71+
const testMatch = ['^.+\\.tsx?$']
7172
jestConfig = {
7273
...jestConfig,
73-
testMatch: ['^.+\\.tsx?$'],
74+
testMatch: jestConfig?.testMatch ? [...jestConfig.testMatch, ...testMatch] : testMatch,
7475
testRegex: jestConfig?.testRegex ? [...testRegex, ...jestConfig.testRegex] : testRegex,
7576
}
7677
const cs = new ConfigSet(getJestConfig(jestConfig, tsJestConfig), parentConfig)
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { Thing } from './main'
2+
3+
export const thing: Thing = { a: 1 }
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface Thing {
2+
a: number
3+
}

src/compiler/__snapshots__/language-service.spec.ts.snap

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ exports[`Language service should compile tsx file for other jsx options 1`] = `
8484
================================================================================
8585
`;
8686

87+
exports[`Language service should do type check for the test file when imported module has changed 1`] = `"src/__mocks__/changed-modules/main.spec.ts(3,14): error TS2741: Property 'b' is missing in type '{ a: number; }' but required in type 'Thing'."`;
88+
8789
exports[`Language service should report diagnostics related to typings with pathRegex config matches file name 1`] = `"test-match-regex-diagnostics.ts(3,7): error TS2322: Type 'number' is not assignable to type 'string'."`;
8890

8991
exports[`Language service should throw error when cannot compile 1`] = `

src/compiler/compiler-utils.ts

-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ import { EXTENSION_REGEX, JSON_REGEX, TS_TSX_REGEX } from '../constants'
99
import { MemoryCache, SourceOutput, TSFiles } from '../types'
1010
import { sha1 } from '../util/sha1'
1111

12-
/**
13-
* @internal
14-
*/
15-
export const hasOwn = Object.prototype.hasOwnProperty
1612
/**
1713
* @internal
1814
*/

src/compiler/language-service.spec.ts

+62-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { LogLevels } from 'bs-logger'
2+
import { readFileSync } from 'fs'
13
import { removeSync, writeFileSync } from 'fs-extra'
24

35
import { makeCompiler } from '../__helpers__/fakers'
@@ -74,7 +76,7 @@ describe('Language service', () => {
7476
jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(spec|test)\.[jt]sx?$/] as any[] },
7577
tsJestConfig: { tsConfig: false },
7678
})
77-
const fileName = 'src/__mocks__/main.spec.ts'
79+
const fileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
7880
const source = `import { Thing } from './main'
7981
8082
export const thing: Thing = { a: 1 }`
@@ -96,7 +98,7 @@ export const thing: Thing = { a: 1 }`
9698
jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(foo|bar)\.[jt]sx?$/] as any[] },
9799
tsJestConfig: { tsConfig: false },
98100
})
99-
const fileName = 'src/__mocks__/main.spec.ts'
101+
const fileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
100102
const source = `import { Thing } from './main'
101103
102104
export const thing: Thing = { a: 1 }`
@@ -197,6 +199,64 @@ export const thing: Thing = { a: 1 }`
197199
removeSync(fileName)
198200
})
199201

202+
it('should not do type check for the test file which is already finished type checking before', () => {
203+
const tmp = tempDir('compiler')
204+
const testFileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
205+
const testFileSrc = readFileSync(testFileName, 'utf-8')
206+
const importedModuleSrc = readFileSync('src/__mocks__/unchanged-modules/main.ts', 'utf-8')
207+
208+
const compiler = makeCompiler({
209+
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/unchanged-modules/*.spec.ts'] },
210+
tsJestConfig: { tsConfig: false },
211+
})
212+
213+
compiler.compile(testFileSrc, testFileName)
214+
logTarget.clear()
215+
compiler.compile(importedModuleSrc, require.resolve('../__mocks__/unchanged-modules/main.ts'))
216+
217+
expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(`
218+
Array [
219+
"[level:20] compileAndCacheResult(): get compile output
220+
",
221+
"[level:20] compileFn(): compiling using language service
222+
",
223+
"[level:20] updateMemoryCache(): update memory cache for language service
224+
",
225+
"[level:20] visitSourceFileNode(): hoisting
226+
",
227+
"[level:20] compileFn(): computing diagnostics using language service
228+
",
229+
]
230+
`)
231+
})
232+
233+
it('should do type check for the test file when imported module has changed', () => {
234+
const tmp = tempDir('compiler')
235+
const testFileName = 'src/__mocks__/changed-modules/main.spec.ts'
236+
const testFileSrc = readFileSync(testFileName, 'utf-8')
237+
const importedModulePath = 'src/__mocks__/changed-modules/main.ts'
238+
const importedModuleSrc = readFileSync(importedModulePath, 'utf-8')
239+
const newImportedModuleSrc = 'export interface Thing { a: number, b: number }'
240+
241+
const compiler1 = makeCompiler({
242+
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/changed-modules/*.spec.ts'] },
243+
tsJestConfig: { tsConfig: false },
244+
})
245+
compiler1.compile(testFileSrc, testFileName)
246+
247+
writeFileSync(importedModulePath, 'export interface Thing { a: number, b: number }')
248+
const compiler2 = makeCompiler({
249+
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/changed-modules/*.spec.ts'] },
250+
tsJestConfig: { tsConfig: false },
251+
})
252+
253+
expect(() =>
254+
compiler2.compile(newImportedModuleSrc, require.resolve('../__mocks__/changed-modules/main.ts')),
255+
).toThrowErrorMatchingSnapshot()
256+
257+
writeFileSync(importedModulePath, importedModuleSrc)
258+
})
259+
200260
it('should report diagnostics related to typings with pathRegex config matches file name', () => {
201261
const fileName = 'test-match-regex-diagnostics.ts'
202262
const source = `

src/compiler/language-service.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
cacheResolvedModules,
1313
getAndCacheProjectReference,
1414
getCompileResultFromReferencedProject,
15-
hasOwn,
1615
isTestFile,
1716
} from './compiler-utils'
1817

@@ -163,7 +162,6 @@ export const initializeLanguageServiceInstance = (
163162
if (isTestFile(configs.testMatchPatterns, fileName)) {
164163
cacheResolvedModules(fileName, code, memoryCache, service.getProgram()!, cacheDir, logger)
165164
} else {
166-
/* istanbul ignore next (covered by e2e) */
167165
Object.entries(memoryCache.resolvedModules)
168166
.filter(entry => {
169167
/**
@@ -172,8 +170,7 @@ export const initializeLanguageServiceInstance = (
172170
* test file for 1st time run after clearing cache because
173171
*/
174172
return (
175-
entry[1].modulePaths.find(modulePath => modulePath === fileName) &&
176-
!hasOwn.call(memoryCache.files, entry[0])
173+
entry[1].modulePaths.find(modulePath => modulePath === fileName) && !memoryCache.files.has(entry[0])
177174
)
178175
})
179176
.forEach(entry => {

0 commit comments

Comments
 (0)