From bac9f19c890f9ea9f90caf8c07384597e97db438 Mon Sep 17 00:00:00 2001 From: abdellah Date: Wed, 2 Nov 2022 09:25:30 +0300 Subject: [PATCH 1/4] display error frame if present --- packages/vitest/src/node/error.ts | 26 +++++++++++++++----------- packages/vitest/src/types/general.ts | 1 + 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/vitest/src/node/error.ts b/packages/vitest/src/node/error.ts index 5ab9ff874b97..e4b2bb3b23b8 100644 --- a/packages/vitest/src/node/error.ts +++ b/packages/vitest/src/node/error.ts @@ -56,19 +56,23 @@ export async function printError(error: unknown, ctx: Vitest, options: PrintErro if (type) printErrorType(type, ctx) - printErrorMessage(e, ctx.logger) - printStack(ctx, stacks, nearest, errorProperties, (s, pos) => { - if (showCodeFrame && s === nearest && nearest) { - const file = fileFromParsedStack(nearest) - // could point to non-existing original file - // for example, when there is a source map file, but no source in node_modules - if (existsSync(file)) { - const sourceCode = readFileSync(file, 'utf-8') - ctx.logger.log(c.yellow(generateCodeFrame(sourceCode, 4, pos))) + if (e.frame) { + ctx.logger.log(c.yellow(e.frame)) + } + else { + printStack(ctx, stacks, nearest, errorProperties, (s, pos) => { + if (showCodeFrame && s === nearest && nearest) { + const file = fileFromParsedStack(nearest) + // could point to non-existing original file + // for example, when there is a source map file, but no source in node_modules + if (existsSync(file)) { + const sourceCode = readFileSync(file, 'utf-8') + ctx.logger.log(c.yellow(generateCodeFrame(sourceCode, 4, pos))) + } } - } - }) + }) + } if (e.cause && 'name' in e.cause) { (e.cause as any).name = `Caused by: ${(e.cause as any).name}` diff --git a/packages/vitest/src/types/general.ts b/packages/vitest/src/types/general.ts index 54f036653da9..3ddfd5ea07b6 100644 --- a/packages/vitest/src/types/general.ts +++ b/packages/vitest/src/types/general.ts @@ -72,6 +72,7 @@ export interface ErrorWithDiff extends Error { expected?: any operator?: string type?: string + frame?: string } export interface ModuleGraphData { From 473f5fcd1806f8439dc13df64c1f2202220e9892 Mon Sep 17 00:00:00 2001 From: abdellah Date: Thu, 3 Nov 2022 14:56:38 +0300 Subject: [PATCH 2/4] add tests for displaying error frame if present --- test/stacktraces/fixtures/frame.spec.imba | 4 +++ test/stacktraces/fixtures/vite.config.ts | 16 ++++++++++ .../test/__snapshots__/runner.test.ts.snap | 22 +++++++++++++ test/stacktraces/test/runner.test.ts | 32 +++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 test/stacktraces/fixtures/frame.spec.imba diff --git a/test/stacktraces/fixtures/frame.spec.imba b/test/stacktraces/fixtures/frame.spec.imba new file mode 100644 index 000000000000..0569dea4a12b --- /dev/null +++ b/test/stacktraces/fixtures/frame.spec.imba @@ -0,0 +1,4 @@ +describe "Test" do + test("1+1") do + expect(1+1).toBe 2 + ciybt. \ No newline at end of file diff --git a/test/stacktraces/fixtures/vite.config.ts b/test/stacktraces/fixtures/vite.config.ts index 766ce8757db1..3a6298137acb 100644 --- a/test/stacktraces/fixtures/vite.config.ts +++ b/test/stacktraces/fixtures/vite.config.ts @@ -4,6 +4,22 @@ export default defineConfig({ plugins: [{ name: 'vite-plugin-imba', transform(code, id) { + if (id === 'frame.test.imba') { + // eslint-disable-next-line no-throw-literal + throw { + name: 'imba-parser error', + id, + message: 'Unexpected \'CALL_END\'', + code, + frame: + '4 | test("1+1") do\n5 | expect(1+1).toBe 2\n6 | ciybt.\n | ^\n7 |\n', + loc: { + line: 3, + column: 11, + file: id, + }, + } + } if (id.endsWith('.imba')) { return { code: diff --git a/test/stacktraces/test/__snapshots__/runner.test.ts.snap b/test/stacktraces/test/__snapshots__/runner.test.ts.snap index 54b488ab5a80..679b4a868203 100644 --- a/test/stacktraces/test/__snapshots__/runner.test.ts.snap +++ b/test/stacktraces/test/__snapshots__/runner.test.ts.snap @@ -1,5 +1,16 @@ // Vitest Snapshot v1 +exports[`stacktraces should pick error frame if present > frame.spec.imba > frame.spec.imba 1`] = ` +" ❯ frame.spec.imba:8:16 + 2| test(\\"1+1\\") do + 3| expect(1+1).toBe 2 + 4| ciybt. + | ^ + +Test Files 1 failed (1) + Tests 1 failed (1)" +`; + exports[`stacktraces should respect sourcemaps > add.test.ts > add.test.ts 1`] = ` " ❯ add.test.ts:12:23 10| @@ -32,3 +43,14 @@ exports[`stacktraces should respect sourcemaps > add-in-js.test.js > add-in-js.t 8| return expect(add(1, 2, 3)).toBe(6) " `; + +exports[`stacktraces should respect sourcemaps > frame.test.imba > frame.test.imba 1`] = ` +" ❯ frame.test.imba:8:16 + 2| test(\\"1+1\\") do + 3| expect(1+1).toBe 2 + 4| ciybt. + | ^ + +Test Files 1 failed (1) + Tests 1 failed (1)" +`; diff --git a/test/stacktraces/test/runner.test.ts b/test/stacktraces/test/runner.test.ts index 748cf22cae5a..f996c2f4b9e2 100644 --- a/test/stacktraces/test/runner.test.ts +++ b/test/stacktraces/test/runner.test.ts @@ -34,3 +34,35 @@ describe('stacktraces should respect sourcemaps', async () => { }, 30000) } }) + +describe('stacktraces should pick error frame if present', async () => { + const root = resolve(__dirname, '../fixtures') + const files = ['frame.spec.imba'] + + for (const file of files) { + it(file, async () => { + // in Windows child_process is very unstable, we skip testing it + if (process.platform === 'win32' && process.env.CI) + return + + let error: any + await execa('npx', ['vitest', 'run', file], { + cwd: root, + env: { + ...process.env, + CI: 'true', + NO_COLOR: 'true', + }, + }) + .catch((e) => { + error = e + }) + + expect(error).toBeTruthy() + const lines = String(error).split(/\n/g) + const index = lines.findIndex(val => val.includes(`${file}:`)) + const msg = lines.slice(index, index + 8).join('\n') + expect(msg).toMatchSnapshot(file) + }, 30000) + } +}) From 3847e4db725fd73666d8645e75326858b00bbc47 Mon Sep 17 00:00:00 2001 From: abdellah Date: Thu, 3 Nov 2022 15:40:03 +0300 Subject: [PATCH 3/4] fix test case to be different than file content --- test/stacktraces/fixtures/vite.config.ts | 4 ++-- test/stacktraces/test/__snapshots__/runner.test.ts.snap | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/stacktraces/fixtures/vite.config.ts b/test/stacktraces/fixtures/vite.config.ts index 3a6298137acb..2b95d8c23309 100644 --- a/test/stacktraces/fixtures/vite.config.ts +++ b/test/stacktraces/fixtures/vite.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ plugins: [{ name: 'vite-plugin-imba', transform(code, id) { - if (id === 'frame.test.imba') { + if (id === 'frame.spec.imba') { // eslint-disable-next-line no-throw-literal throw { name: 'imba-parser error', @@ -12,7 +12,7 @@ export default defineConfig({ message: 'Unexpected \'CALL_END\'', code, frame: - '4 | test("1+1") do\n5 | expect(1+1).toBe 2\n6 | ciybt.\n | ^\n7 |\n', + '4 | test("1+1") do\n5 | expect(1+1).toBe 2\n6 | frame.\n | ^\n7 |\n', loc: { line: 3, column: 11, diff --git a/test/stacktraces/test/__snapshots__/runner.test.ts.snap b/test/stacktraces/test/__snapshots__/runner.test.ts.snap index 679b4a868203..36439280cec2 100644 --- a/test/stacktraces/test/__snapshots__/runner.test.ts.snap +++ b/test/stacktraces/test/__snapshots__/runner.test.ts.snap @@ -4,7 +4,7 @@ exports[`stacktraces should pick error frame if present > frame.spec.imba > fram " ❯ frame.spec.imba:8:16 2| test(\\"1+1\\") do 3| expect(1+1).toBe 2 - 4| ciybt. + 4| frame. | ^ Test Files 1 failed (1) From 6618e90109761cdf17c668b275b8c8dc1a4616a0 Mon Sep 17 00:00:00 2001 From: abdellah Date: Thu, 3 Nov 2022 21:56:56 +0300 Subject: [PATCH 4/4] update snapshot to match error frame --- test/stacktraces/fixtures/frame.spec.imba | 2 +- test/stacktraces/fixtures/vite.config.ts | 2 +- .../test/__snapshots__/runner.test.ts.snap | 25 ++++++------------- test/stacktraces/test/runner.test.ts | 2 +- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/test/stacktraces/fixtures/frame.spec.imba b/test/stacktraces/fixtures/frame.spec.imba index 0569dea4a12b..b8bffe118079 100644 --- a/test/stacktraces/fixtures/frame.spec.imba +++ b/test/stacktraces/fixtures/frame.spec.imba @@ -1,4 +1,4 @@ describe "Test" do test("1+1") do expect(1+1).toBe 2 - ciybt. \ No newline at end of file + ciyet. \ No newline at end of file diff --git a/test/stacktraces/fixtures/vite.config.ts b/test/stacktraces/fixtures/vite.config.ts index 2b95d8c23309..06b1f1e82a9b 100644 --- a/test/stacktraces/fixtures/vite.config.ts +++ b/test/stacktraces/fixtures/vite.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ plugins: [{ name: 'vite-plugin-imba', transform(code, id) { - if (id === 'frame.spec.imba') { + if (id.endsWith('frame.spec.imba')) { // eslint-disable-next-line no-throw-literal throw { name: 'imba-parser error', diff --git a/test/stacktraces/test/__snapshots__/runner.test.ts.snap b/test/stacktraces/test/__snapshots__/runner.test.ts.snap index 36439280cec2..c3eba873f8a9 100644 --- a/test/stacktraces/test/__snapshots__/runner.test.ts.snap +++ b/test/stacktraces/test/__snapshots__/runner.test.ts.snap @@ -1,14 +1,14 @@ // Vitest Snapshot v1 exports[`stacktraces should pick error frame if present > frame.spec.imba > frame.spec.imba 1`] = ` -" ❯ frame.spec.imba:8:16 - 2| test(\\"1+1\\") do - 3| expect(1+1).toBe 2 - 4| frame. - | ^ +" ❯ frame.spec.imba (0 test) -Test Files 1 failed (1) - Tests 1 failed (1)" +4 | test(\\"1+1\\") do +5 | expect(1+1).toBe 2 +6 | frame. + | ^ +7 | +" `; exports[`stacktraces should respect sourcemaps > add.test.ts > add.test.ts 1`] = ` @@ -43,14 +43,3 @@ exports[`stacktraces should respect sourcemaps > add-in-js.test.js > add-in-js.t 8| return expect(add(1, 2, 3)).toBe(6) " `; - -exports[`stacktraces should respect sourcemaps > frame.test.imba > frame.test.imba 1`] = ` -" ❯ frame.test.imba:8:16 - 2| test(\\"1+1\\") do - 3| expect(1+1).toBe 2 - 4| ciybt. - | ^ - -Test Files 1 failed (1) - Tests 1 failed (1)" -`; diff --git a/test/stacktraces/test/runner.test.ts b/test/stacktraces/test/runner.test.ts index f996c2f4b9e2..2e96047586e6 100644 --- a/test/stacktraces/test/runner.test.ts +++ b/test/stacktraces/test/runner.test.ts @@ -60,7 +60,7 @@ describe('stacktraces should pick error frame if present', async () => { expect(error).toBeTruthy() const lines = String(error).split(/\n/g) - const index = lines.findIndex(val => val.includes(`${file}:`)) + const index = lines.findIndex(val => val.includes('(0 test)')) const msg = lines.slice(index, index + 8).join('\n') expect(msg).toMatchSnapshot(file) }, 30000)