Skip to content

Commit d03e0e7

Browse files
committed
feat: io serializer + other test utils
1 parent 6a7f01f commit d03e0e7

20 files changed

Lines changed: 659 additions & 142 deletions

.npmignore

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Tests
2-
e2e/
2+
e2e
33

44
# sources are inlined
5-
src/
5+
src
66

77
# Developement scripts
8-
scripts/
8+
scripts
99

1010
# Logs
1111
logs
@@ -24,7 +24,7 @@ pids
2424
lib-cov
2525

2626
# Coverage directory used by tools like istanbul
27-
coverage/
27+
coverage
2828

2929
# nyc test coverage
3030
.nyc_output
@@ -39,15 +39,15 @@ coverage/
3939
build/Release
4040

4141
# Dependency directories
42-
node_modules/
43-
jspm_packages/
42+
node_modules
43+
jspm_packages
4444

4545
# Optional npm cache directory
4646
.npm
4747

4848
# Optional REPL history
4949
.node_repl_history
5050
# while refactoring...
51-
old/
51+
old
5252

53-
*.tgz
53+
*.tgz

e2e/__cases__/hoisting/hello.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import hello from './hello';
22

3+
afterAll(() => {
4+
// this should go after
5+
jest.unmock('./hello');
6+
})
7+
38
jest.mock('./hello');
49

510
describe('hello', () => {
@@ -9,5 +14,7 @@ describe('hello', () => {
914
expect(hello).not.toBe(original);
1015
expect(msg).toBeUndefined();
1116
expect(hello).toHaveProperty('mock');
17+
expect(require('foo')).toBe('bar');
18+
jest.mock('foo', () => 'bar', { virtual: true });
1219
});
1320
});

e2e/__helpers__/test-case.ts

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// tslint:disable-file:no-shadowed-variable
22
import { sync as spawnSync } from 'cross-spawn'
3-
import { join, relative, sep } from 'path'
3+
import { join, relative, sep, isAbsolute } from 'path'
44
import * as Paths from '../../scripts/lib/paths'
55
import * as fs from 'fs-extra'
66
import { RawSourceMap } from 'source-map'
7-
import { relativiseSourceRoot, extractSourceMaps } from './source-maps'
7+
import { extractSourceMaps } from './source-maps'
88
import { SpawnSyncReturns } from 'child_process'
99
import merge from 'lodash.merge'
1010
import { TsJestConfig } from '../../src/lib/types'
11+
import { rewriteSourceMaps, relativisePaths } from '../../src/__helpers__/source-maps'
1112

1213
const TEMPLATE_EXCLUDED_ITEMS = ['node_modules', 'package-lock.json']
1314

@@ -144,35 +145,57 @@ export class TestRunResult {
144145
constructor(
145146
readonly cwd: string,
146147
readonly result: SpawnSyncReturns<Buffer>,
147-
readonly ioDir?: string,
148+
readonly context: Readonly<{
149+
ioDir?: string | undefined,
150+
cmd: string,
151+
args: string[],
152+
env: { [key: string]: string },
153+
}>,
148154
) { }
149155
get isPass() { return this.status === 0 }
150156
get isFail() { return !this.isPass }
151157
get status() { return this.result.status }
152158
get output() { return stripAnsiColors((this.result.output ? this.result.output.join('\n\n') : '')) }
153159
get stderr() { return stripAnsiColors((this.result.stderr || '').toString()) }
154160
get stdout() { return stripAnsiColors((this.result.stdout || '').toString()) }
161+
get cmdLine() {
162+
return [this.context.cmd, ...this.context.args].join(' ')
163+
}
155164
ioFor(relFilePath: string): TestFileIo {
156-
if (!this.ioDir) {
165+
if (!this.context.ioDir) {
157166
throw new Error('IO not written for test, you must configure the test with `writeIo: true`.')
158167
}
159-
const io = require(`${this.ioDir}/${relFilePath}.json`)
160-
return new TestFileIo(this.cwd, io.in, io.out)
168+
const io = require(`${this.context.ioDir}/${relFilePath}.json`)
169+
return new TestFileIo(this.cwd, relFilePath, io.in, io.out)
161170
}
162171
}
163172

164173
// tslint:disable-next-line:max-classes-per-file
165-
class TestFileIo {
174+
export class TestFileIo {
166175
constructor(
167176
private _cwd: string,
177+
readonly filename: string,
168178
readonly input: [string, jest.Path, jest.ProjectConfig, jest.TransformOptions?],
169179
readonly output: string | jest.TransformedSource,
170180
) { }
171181
get inputCode(): string { return this.input[0] }
172182
get inputPath(): string { return this.input[1] }
173183
get outputCode(): string { return typeof this.output === 'object' ? this.output.code : this.output }
174184
get outputSourceMaps(): RawSourceMap | undefined { return extractSourceMaps(this.outputCode) }
175-
get normalizedOutputCode(): string { return relativiseSourceRoot(this._cwd, this.outputCode, '<cwd>/') }
185+
get normalizedOutputCode(): string {
186+
return rewriteSourceMaps(
187+
this.outputCode,
188+
this.sourceMapsNormalizer,
189+
)
190+
}
191+
get normalizedOutputSourceMaps(): RawSourceMap | undefined {
192+
const maps = this.outputSourceMaps
193+
if (maps) return this.sourceMapsNormalizer(maps)
194+
return
195+
}
196+
get sourceMapsNormalizer() {
197+
return (maps: RawSourceMap): RawSourceMap => relativisePaths(maps, this._cwd, '<cwd>/')
198+
}
176199
}
177200

178201
// tslint:disable-next-line:interface-over-type-literal
@@ -240,6 +263,7 @@ export function run(name: string, options: RunTestOptions = {}): TestRunResult {
240263
)
241264
const pkg = require(join(dir, 'package.json'))
242265

266+
let shortCmd: string
243267
let cmdArgs: string[] = []
244268
if (inject) {
245269
cmdArgs.push('--testPathPattern="/__eval\\\\.ts$"')
@@ -253,8 +277,10 @@ export function run(name: string, options: RunTestOptions = {}): TestRunResult {
253277
cmdArgs.unshift('--')
254278
}
255279
cmdArgs = ['npm', '-s', 'run', 'test', ...cmdArgs]
280+
shortCmd = 'npm'
256281
} else {
257282
cmdArgs.unshift(join(dir, 'node_modules', '.bin', 'jest'))
283+
shortCmd = 'jest'
258284
}
259285

260286
// merge given config extend
@@ -316,7 +342,12 @@ export function run(name: string, options: RunTestOptions = {}): TestRunResult {
316342
})
317343
})
318344

319-
return new TestRunResult(fs.realpathSync(dir), result, writeIo ? ioDir : undefined)
345+
return new TestRunResult(fs.realpathSync(dir), result, {
346+
cmd: shortCmd,
347+
args: cmdArgs,
348+
env: mergedEnv,
349+
ioDir: writeIo ? ioDir : undefined,
350+
})
320351
}
321352

322353
// from https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { TestFileIo } from '../__helpers__/test-case'
2+
import { safeDump } from 'js-yaml'
3+
4+
export const test = (val: any) => val && val instanceof TestFileIo
5+
export const print = (val: TestFileIo, serialize: any, indent: any) => {
6+
const sourceMaps = val.normalizedOutputSourceMaps
7+
const out = [
8+
`===[ FILE: ${val.filename.replace(/\\/g, '/')} ]${'='.repeat(67 - val.filename.length)}`,
9+
val.normalizedOutputCode,
10+
...(sourceMaps ? [
11+
`===[ INLINE SOURCE MAPS ]${'='.repeat(55)}`,
12+
safeDump(sourceMaps, {sortKeys: true, noRefs: true, noCompatMode: true}).trim(),
13+
] : []),
14+
'='.repeat(80),
15+
]
16+
.map(l => indent(l))
17+
.join('\n')
18+
return `${out}`
19+
}

e2e/__serializers__/test-run-result.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
export const test = (val: any) => val && val instanceof TestRunResult
77
export const print = (val: TestRunResult, serialize: any, indent: any) => {
88
const out = [
9+
`${val.status === 0 ? '√' : '×'} ${val.cmdLine}`,
10+
`↳ exit code: ${val.status}`,
911
`===[ STDOUT ]${'='.repeat(67)}`,
1012
sanitizeOutput(val.stdout),
1113
`===[ STDERR ]${'='.repeat(67)}`,
@@ -14,5 +16,5 @@ export const print = (val: TestRunResult, serialize: any, indent: any) => {
1416
]
1517
.map(l => indent(l))
1618
.join('\n')
17-
return `jest exit code: ${val.status}\n${out}`
19+
return out
1820
}

0 commit comments

Comments
 (0)