Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: correct unit tests and e2e tests for language service #1579

Merged
merged 1 commit into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 3 additions & 153 deletions e2e/__tests__/__snapshots__/diagnostics.test.ts.snap
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface Thing {
a: number
}
2 changes: 2 additions & 0 deletions src/compiler/__snapshots__/language-service.spec.ts.snap
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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(`
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just need to verify logging for assertion related to https://github.com/kulshekhar/ts-jest/pull/1579/files#diff-124008e76d6a710666b8d995ffc3758fR173 (the condition which is fixed in the below comment)

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
Original file line number Diff line number Diff line change
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])
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified our internal memory cache in #1574 but forgot this one. It doesn't cause any bugs or performance issue but 'the fastest code is the code which does nothing' so it's better to correct this condition.

)
})
.forEach(entry => {
Expand Down