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

feat(ui): show unhandled errors on the ui #4380

Merged
merged 26 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
edfc76b
feat(ui): show unhandled errors on the ui
spiroka Oct 26, 2023
ed06d00
chore: show unhandled errors in html report
spiroka Oct 28, 2023
3a71dc1
chore: added tests
spiroka Nov 2, 2023
753885e
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 2, 2023
2f103fc
chore: fix typo
spiroka Nov 2, 2023
e80dd91
Merge branch 'unhandled-errors-in-ui' of https://github.com/spiroka/v…
spiroka Nov 2, 2023
d0d0863
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 2, 2023
88ddb3d
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 7, 2023
a75c1f2
chore: update snapshots
spiroka Nov 7, 2023
2e4a8a4
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 9, 2023
8afb14e
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 13, 2023
b5e42a5
chore: get unhandled errors in Promise.all
spiroka Nov 13, 2023
eafe0de
chore: show error details
spiroka Nov 19, 2023
311c2fb
chore: inline isPrimitive
spiroka Nov 20, 2023
1c7607a
chore: don't export inlined function
spiroka Nov 20, 2023
0557eb9
Merge branch 'main' into unhandled-errors-in-ui
spiroka Nov 20, 2023
7dd446f
chore: added tests for error details
spiroka Nov 21, 2023
a491c46
Merge branch 'unhandled-errors-in-ui' of https://github.com/spiroka/v…
spiroka Nov 21, 2023
ca3a82e
chore:added stack traces, did some rewording
spiroka Dec 15, 2023
5311c62
Merge branch 'main' into unhandled-errors-in-ui
spiroka Dec 15, 2023
db4f07d
Merge remote-tracking branch 'upstream/main' into unhandled-errors-in-ui
spiroka Dec 20, 2023
b6de84a
Merge branch 'main' into unhandled-errors-in-ui
spiroka Dec 26, 2023
65f01f3
Merge branch 'main' into unhandled-errors-in-ui
spiroka Jan 2, 2024
0e59875
Merge branch 'main' into unhandled-errors-in-ui
spiroka Jan 5, 2024
68f9407
Merge branch 'main' into unhandled-errors-in-ui
sheremet-va Jan 12, 2024
a8da5cd
chore: cleanup
sheremet-va Jan 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 22 additions & 1 deletion packages/ui/client/components/dashboard/TestFilesEntry.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { files } from '../../composables/client'
import { files, unhandledErrors } from '../../composables/client'
import { filesFailed, filesSnapshotFailed, filesSuccess, time } from '../../composables/summary'
</script>

Expand Down Expand Up @@ -44,12 +44,33 @@ import { filesFailed, filesSnapshotFailed, filesSuccess, time } from '../../comp
</div>
</template>

<template v-if="unhandledErrors.length">
<div i-carbon-checkmark-outline-error />
<div>
Errors
</div>
<div class="number" text-red5>
{{ unhandledErrors.length }}
</div>
</template>

<div i-carbon-timer />
<div>Time</div>
<div class="number" data-testid="run-time">
{{ time }}
</div>
</div>
<template v-if="unhandledErrors.length">
<div bg="red500/10" text="red500" p="x3 y2" max-w-xl m-2 rounded>
<h3 text-center mb-2>
Unhandled Errors
</h3>
<p text="sm" font-thin data-testid="unhandled-errors">
Vitest caught {{ unhandledErrors.length }} error{{ unhandledErrors.length > 1 ? 's' : '' }} during the test run.<br>
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.
sheremet-va marked this conversation as resolved.
Show resolved Hide resolved
</p>
</div>
</template>
</template>

<style scoped>
Expand Down
5 changes: 4 additions & 1 deletion packages/ui/client/composables/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { createStaticClient } from './static'
export { ENTRY_URL, PORT, HOST, isReport } from '../../constants'

export const testRunState: Ref<RunState> = ref('idle')
export const unhandledErrors: Ref<unknown[]> = ref([])

export const client = (function createVitestClient() {
if (isReport) {
Expand All @@ -23,8 +24,9 @@ export const client = (function createVitestClient() {
onTaskUpdate() {
testRunState.value = 'running'
},
onFinished() {
onFinished(_files, errors) {
testRunState.value = 'idle'
unhandledErrors.value = errors || []
},
},
})
Expand Down Expand Up @@ -75,6 +77,7 @@ watch(
client.rpc.getConfig(),
])
client.state.collectFiles(files)
unhandledErrors.value = await client.rpc.getUnhandledErrors()
sheremet-va marked this conversation as resolved.
Show resolved Hide resolved
config.value = _config
})

Expand Down
10 changes: 8 additions & 2 deletions packages/ui/client/composables/client/static.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { BirpcReturn } from 'birpc'
import type { VitestClient } from '@vitest/ws-client'
import type { WebSocketHandlers } from 'vitest/src/api/types'
import type { WebSocketEvents, WebSocketHandlers } from 'vitest/src/api/types'
import { parse } from 'flatted'
import { decompressSync, strFromU8 } from 'fflate'
import type { File, ModuleGraphData, ResolvedConfig } from 'vitest/src/types'
Expand All @@ -11,6 +11,7 @@ interface HTMLReportMetadata {
files: File[]
config: ResolvedConfig
moduleGraph: Record<string, ModuleGraphData>
unhandledErrors: unknown[]
}

const noop: any = () => {}
Expand Down Expand Up @@ -42,6 +43,9 @@ export function createStaticClient(): VitestClient {
getModuleGraph: async (id) => {
return metadata.moduleGraph[id]
},
getUnhandledErrors: () => {
return metadata.unhandledErrors
},
getTransformResult: async (id) => {
return {
code: id,
Expand All @@ -66,9 +70,11 @@ export function createStaticClient(): VitestClient {
saveSnapshotFile: asyncNoop,
readTestFile: asyncNoop,
removeSnapshotFile: asyncNoop,
onUnhandledError: noop,
saveTestFile: asyncNoop,
} as WebSocketHandlers

ctx.rpc = rpc as any as BirpcReturn<WebSocketHandlers>
ctx.rpc = rpc as any as BirpcReturn<WebSocketHandlers, WebSocketEvents>

let openPromise: Promise<void>

Expand Down
2 changes: 2 additions & 0 deletions packages/ui/node/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface HTMLReportData {
files: File[]
config: ResolvedConfig
moduleGraph: Record<string, ModuleGraphData>
unhandledErrors: unknown[]
}

const distDir = resolve(fileURLToPath(import.meta.url), '../../dist')
Expand All @@ -47,6 +48,7 @@ export default class HTMLReporter implements Reporter {
paths: this.ctx.state.getPaths(),
files: this.ctx.state.getFiles(),
config: this.ctx.config,
unhandledErrors: this.ctx.state.getUnhandledErrors(),
moduleGraph: {},
}
await Promise.all(
Expand Down
7 changes: 5 additions & 2 deletions packages/vitest/src/api/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ export function setup(vitestOrWorkspace: Vitest | WorkspaceProject, server?: Vit
getProvidedContext() {
return 'ctx' in vitestOrWorkspace ? vitestOrWorkspace.getProvidedContext() : ({} as any)
},
getUnhandledErrors() {
return ctx.state.getUnhandledErrors()
},
},
{
post: msg => ws.send(msg),
Expand Down Expand Up @@ -194,9 +197,9 @@ class WebSocketReporter implements Reporter {
})
}

onFinished(files?: File[] | undefined) {
onFinished(files?: File[], errors?: unknown[]) {
this.clients.forEach((client) => {
client.onFinished?.(files)
client.onFinished?.(files, errors)
})
}

Expand Down
1 change: 1 addition & 0 deletions packages/vitest/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface WebSocketHandlers {
rerun(files: string[]): Promise<void>
updateSnapshot(file?: File): Promise<void>
getProvidedContext(): ProvidedContext
getUnhandledErrors(): unknown[]
}

export interface WebSocketEvents extends Pick<Reporter, 'onCollected' | 'onFinished' | 'onTaskUpdate' | 'onUserConsoleLog' | 'onPathsCollected'> {
Expand Down
4 changes: 2 additions & 2 deletions packages/ws-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export function createClient(url: string, options: VitestClientOptions = {}) {
onUserConsoleLog(log) {
ctx.state.updateUserLog(log)
},
onFinished(files) {
handlers.onFinished?.(files)
onFinished(files, errors) {
handlers.onFinished?.(files, errors)
},
onCancel(reason: CancelReason) {
handlers.onCancel?.(reason)
Expand Down
2 changes: 2 additions & 0 deletions test/reporters/tests/__snapshots__/html.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ exports[`html reporter > resolves to "failing" status for test file "json-fail"
"paths": [
"<rootDir>/test/reporters/fixtures/json-fail.test.ts",
],
"unhandledErrors": [],
}
`;

Expand Down Expand Up @@ -226,5 +227,6 @@ exports[`html reporter > resolves to "passing" status for test file "all-passing
"paths": [
"<rootDir>/test/reporters/fixtures/all-passing-or-skipped.test.ts",
],
"unhandledErrors": [],
}
`;
3 changes: 3 additions & 0 deletions test/ui/fixtures/sample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@ import { expect, it } from 'vitest'
it('add', () => {
// eslint-disable-next-line no-console
console.log('log test')
setTimeout(() => {
throw new Error('error')
})
expect(1 + 1).toEqual(2)
})
14 changes: 12 additions & 2 deletions test/ui/test/html-report.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,18 @@ describe.skipIf(isWindows)('html report', () => {
return exit
})

it('dashboard', async () => {
await untilUpdated(() => page.textContent('[aria-labelledby]'), '1 Pass 0 Fail 1 Total ')
describe('dashboard', async () => {
it('summary', async () => {
await untilUpdated(() => page.textContent('[aria-labelledby]'), '1 Pass 0 Fail 1 Total ')
})

it('unhandled errors', async () => {
await untilUpdated(
() => page.textContent('[data-testid=unhandled-errors]'),
'Vitest caught 1 error during the test run. This might cause false positive tests. '
+ 'Resolve unhandled errors to make sure your tests are not affected.',
)
})
})

describe('file detail', async () => {
Expand Down
14 changes: 12 additions & 2 deletions test/ui/test/ui.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,18 @@ describe.skipIf(isWindows)('ui', () => {
return exit
})

it('dashboard', async () => {
await untilUpdated(() => page.textContent('[aria-labelledby]'), '1 Pass 0 Fail 1 Total ')
describe('dashboard', async () => {
it('summary', async () => {
await untilUpdated(() => page.textContent('[aria-labelledby]'), '1 Pass 0 Fail 1 Total ')
})

it('unhandled errors', async () => {
await untilUpdated(
() => page.textContent('[data-testid=unhandled-errors]'),
'Vitest caught 1 error during the test run. This might cause false positive tests. '
+ 'Resolve unhandled errors to make sure your tests are not affected.',
)
})
})

describe('file detail', async () => {
Expand Down