Skip to content

Commit

Permalink
test: correct unit tests and e2e tests for language service (#1579)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahnpnl committed May 4, 2020
1 parent 9335b77 commit de59e3f
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 210 deletions.
156 changes: 3 additions & 153 deletions e2e/__tests__/__snapshots__/diagnostics.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`With diagnostics throw first throw should fail using template "default" 1`] = `
exports[`With diagnostics throw should fail using template "default" 1`] = `
× jest
↳ exit code: 1
===[ STDOUT ]===================================================================
Expand All @@ -27,7 +27,7 @@ exports[`With diagnostics throw first throw should fail using template "default"
================================================================================
`;

exports[`With diagnostics throw first throw should fail using template "with-babel-7" 1`] = `
exports[`With diagnostics throw should fail using template "with-babel-7" 1`] = `
× jest
↳ exit code: 1
===[ STDOUT ]===================================================================
Expand All @@ -54,7 +54,7 @@ exports[`With diagnostics throw first throw should fail using template "with-bab
================================================================================
`;

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

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`] = `
× jest
↳ exit code: 1
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
FAIL ./main.spec.ts
× foo is 42
● foo is 42
expect(received).toBe(expected) // Object.is equality
Expected: 42
Received: 43
4 |
5 | test('foo is 42', () => {
> 6 | expect(foo).toBe(42);
| ^
7 | });
8 |
at Object.<anonymous> (main.spec.ts:6:15)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
× jest
↳ exit code: 1
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
FAIL ./main.spec.ts
× foo is 42
● foo is 42
expect(received).toBe(expected) // Object.is equality
Expected: 42
Received: 43
4 |
5 | test('foo is 42', () => {
> 6 | expect(foo).toBe(42);
| ^
7 | });
8 |
at Object.<anonymous> (main.spec.ts:6:15)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
× jest
↳ exit code: 1
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
FAIL ./main.spec.ts
× foo is 42
● foo is 42
expect(received).toBe(expected) // Object.is equality
Expected: 42
Received: 43
4 |
5 | test('foo is 42', () => {
> 6 | expect(foo).toBe(42);
| ^
7 | });
8 |
at Object.<anonymous> (main.spec.ts:6:15)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./main.spec.ts
√ foo is 42
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./main.spec.ts
√ foo is 42
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./main.spec.ts
√ foo is 42
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`With diagnostics warn only should pass using template "default" 1`] = `
√ jest --no-cache
↳ exit code: 0
Expand Down
51 changes: 5 additions & 46 deletions e2e/__tests__/diagnostics.test.ts
@@ -1,55 +1,14 @@
import { writeFileSync } from 'fs'
import { join } from 'path'

import { allValidPackageSets } from '../__helpers__/templates'
import { configureTestCase } from '../__helpers__/test-case'

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

describe('first throw', () => {
testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(1)
expect(result).toMatchSnapshot()
})
})
})

describe('then pass when type has changed to valid base on cache of the previous run', () => {
beforeAll(() => {
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number }`)
})

afterAll(() => {
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`)
})

testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(0)
expect(result).toMatchSnapshot()
})
})
})

describe('then fail when code has changed to invalid base on cache of the previous run', () => {
beforeAll(() => {
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 43\nexport type Thing = { a: number }`)
})

afterAll(() => {
writeFileSync(join(__dirname, '../__cases__/diagnostics/throw/main.ts'), `export const foo = 42\nexport type Thing = { a: number, b: number }\n`)
})

testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(1)
expect(result).toMatchSnapshot()
})
testCase.runWithTemplates(allValidPackageSets, 1, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(1)
expect(result).toMatchSnapshot()
})
})
})
Expand Down
3 changes: 2 additions & 1 deletion src/__helpers__/fakers.ts
Expand Up @@ -68,9 +68,10 @@ export function makeCompiler({
pretty: false,
}
const testRegex = ['^.+\\.[tj]sx?$']
const testMatch = ['^.+\\.tsx?$']
jestConfig = {
...jestConfig,
testMatch: ['^.+\\.tsx?$'],
testMatch: jestConfig?.testMatch ? [...jestConfig.testMatch, ...testMatch] : testMatch,
testRegex: jestConfig?.testRegex ? [...testRegex, ...jestConfig.testRegex] : testRegex,
}
const cs = new ConfigSet(getJestConfig(jestConfig, tsJestConfig), parentConfig)
Expand Down
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions src/__mocks__/unchanged-modules/main.spec.ts
@@ -0,0 +1,3 @@
import { Thing } from './main'

export const thing: Thing = { a: 1 }
3 changes: 3 additions & 0 deletions src/__mocks__/unchanged-modules/main.ts
@@ -0,0 +1,3 @@
export interface Thing {
a: number
}
2 changes: 2 additions & 0 deletions src/compiler/__snapshots__/language-service.spec.ts.snap
Expand Up @@ -84,6 +84,8 @@ exports[`Language service should compile tsx file for other jsx options 1`] = `
================================================================================
`;

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'."`;

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'."`;

exports[`Language service should throw error when cannot compile 1`] = `
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/compiler-utils.ts
Expand Up @@ -9,10 +9,6 @@ import { EXTENSION_REGEX, JSON_REGEX, TS_TSX_REGEX } from '../constants'
import { MemoryCache, SourceOutput, TSFiles } from '../types'
import { sha1 } from '../util/sha1'

/**
* @internal
*/
export const hasOwn = Object.prototype.hasOwnProperty
/**
* @internal
*/
Expand Down
64 changes: 62 additions & 2 deletions src/compiler/language-service.spec.ts
@@ -1,3 +1,5 @@
import { LogLevels } from 'bs-logger'
import { readFileSync } from 'fs'
import { removeSync, writeFileSync } from 'fs-extra'

import { makeCompiler } from '../__helpers__/fakers'
Expand Down Expand Up @@ -74,7 +76,7 @@ describe('Language service', () => {
jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(spec|test)\.[jt]sx?$/] as any[] },
tsJestConfig: { tsConfig: false },
})
const fileName = 'src/__mocks__/main.spec.ts'
const fileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
const source = `import { Thing } from './main'
export const thing: Thing = { a: 1 }`
Expand All @@ -96,7 +98,7 @@ export const thing: Thing = { a: 1 }`
jestConfig: { cache: true, cacheDirectory: tmp, testRegex: [/.*\.(foo|bar)\.[jt]sx?$/] as any[] },
tsJestConfig: { tsConfig: false },
})
const fileName = 'src/__mocks__/main.spec.ts'
const fileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
const source = `import { Thing } from './main'
export const thing: Thing = { a: 1 }`
Expand Down Expand Up @@ -197,6 +199,64 @@ export const thing: Thing = { a: 1 }`
removeSync(fileName)
})

it('should not do type check for the test file which is already finished type checking before', () => {
const tmp = tempDir('compiler')
const testFileName = 'src/__mocks__/unchanged-modules/main.spec.ts'
const testFileSrc = readFileSync(testFileName, 'utf-8')
const importedModuleSrc = readFileSync('src/__mocks__/unchanged-modules/main.ts', 'utf-8')

const compiler = makeCompiler({
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/unchanged-modules/*.spec.ts'] },
tsJestConfig: { tsConfig: false },
})

compiler.compile(testFileSrc, testFileName)
logTarget.clear()
compiler.compile(importedModuleSrc, require.resolve('../__mocks__/unchanged-modules/main.ts'))

expect(logTarget.filteredLines(LogLevels.debug, Infinity)).toMatchInlineSnapshot(`
Array [
"[level:20] compileAndCacheResult(): get compile output
",
"[level:20] compileFn(): compiling using language service
",
"[level:20] updateMemoryCache(): update memory cache for language service
",
"[level:20] visitSourceFileNode(): hoisting
",
"[level:20] compileFn(): computing diagnostics using language service
",
]
`)
})

it('should do type check for the test file when imported module has changed', () => {
const tmp = tempDir('compiler')
const testFileName = 'src/__mocks__/changed-modules/main.spec.ts'
const testFileSrc = readFileSync(testFileName, 'utf-8')
const importedModulePath = 'src/__mocks__/changed-modules/main.ts'
const importedModuleSrc = readFileSync(importedModulePath, 'utf-8')
const newImportedModuleSrc = 'export interface Thing { a: number, b: number }'

const compiler1 = makeCompiler({
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/changed-modules/*.spec.ts'] },
tsJestConfig: { tsConfig: false },
})
compiler1.compile(testFileSrc, testFileName)

writeFileSync(importedModulePath, 'export interface Thing { a: number, b: number }')
const compiler2 = makeCompiler({
jestConfig: { cache: true, cacheDirectory: tmp, testMatch: ['src/__mocks__/changed-modules/*.spec.ts'] },
tsJestConfig: { tsConfig: false },
})

expect(() =>
compiler2.compile(newImportedModuleSrc, require.resolve('../__mocks__/changed-modules/main.ts')),
).toThrowErrorMatchingSnapshot()

writeFileSync(importedModulePath, importedModuleSrc)
})

it('should report diagnostics related to typings with pathRegex config matches file name', () => {
const fileName = 'test-match-regex-diagnostics.ts'
const source = `
Expand Down
5 changes: 1 addition & 4 deletions src/compiler/language-service.ts
Expand Up @@ -12,7 +12,6 @@ import {
cacheResolvedModules,
getAndCacheProjectReference,
getCompileResultFromReferencedProject,
hasOwn,
isTestFile,
} from './compiler-utils'

Expand Down Expand Up @@ -163,7 +162,6 @@ export const initializeLanguageServiceInstance = (
if (isTestFile(configs.testMatchPatterns, fileName)) {
cacheResolvedModules(fileName, code, memoryCache, service.getProgram()!, cacheDir, logger)
} else {
/* istanbul ignore next (covered by e2e) */
Object.entries(memoryCache.resolvedModules)
.filter(entry => {
/**
Expand All @@ -172,8 +170,7 @@ export const initializeLanguageServiceInstance = (
* test file for 1st time run after clearing cache because
*/
return (
entry[1].modulePaths.find(modulePath => modulePath === fileName) &&
!hasOwn.call(memoryCache.files, entry[0])
entry[1].modulePaths.find(modulePath => modulePath === fileName) && !memoryCache.files.has(entry[0])
)
})
.forEach(entry => {
Expand Down

0 comments on commit de59e3f

Please sign in to comment.