Skip to content

Commit 053e8b0

Browse files
authored
feat(browser): support custom kind in page.mark (#10302)
1 parent ea55eb3 commit 053e8b0

9 files changed

Lines changed: 108 additions & 12 deletions

File tree

‎docs/api/browser/context.md‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,11 @@ export const page: {
8282
/**
8383
* Add a trace marker when browser tracing is enabled.
8484
*/
85-
mark(name: string, options?: { stack?: string }): Promise<void>
85+
mark(name: string, options?: { stack?: string; kind?: BrowserTraceEntryKind }): Promise<void>
8686
/**
8787
* Group multiple operations under a trace marker when browser tracing is enabled.
8888
*/
89-
mark<T>(name: string, body: () => T | Promise<T>, options?: { stack?: string }): Promise<T>
89+
mark<T>(name: string, body: () => T | Promise<T>, options?: { stack?: string; kind?: BrowserTraceEntryKind }): Promise<T>
9090
/**
9191
* Extend default `page` object with custom methods.
9292
*/
@@ -127,18 +127,20 @@ The `path` is also ignored in that case.
127127
### mark
128128
129129
```ts
130-
function mark(name: string, options?: { stack?: string }): Promise<void>
130+
function mark(name: string, options?: { stack?: string; kind?: BrowserTraceEntryKind }): Promise<void>
131131
function mark<T>(
132132
name: string,
133133
body: () => T | Promise<T>,
134-
options?: { stack?: string },
134+
options?: { stack?: string; kind?: BrowserTraceEntryKind },
135135
): Promise<T>
136136
```
137137

138138
Adds a named marker to the trace timeline for the current test.
139139

140140
Pass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location.
141141

142+
Pass `options.kind` to categorize your marker as specific type, for example as `'action'`.
143+
142144
If you pass a callback, Vitest creates a trace group with this name, runs the callback, and closes the group automatically.
143145

144146
```ts
@@ -151,7 +153,7 @@ await page.mark('after submit')
151153
await page.mark('submit flow', async () => {
152154
await page.getByRole('textbox', { name: 'Email' }).fill('[email protected]')
153155
await page.getByRole('button', { name: 'Submit' }).click()
154-
})
156+
}, { kind: 'action' })
155157
```
156158

157159
::: tip

‎docs/api/browser/locators.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -846,13 +846,15 @@ The `path` is also ignored in that case.
846846
### mark
847847

848848
```ts
849-
function mark(name: string, options?: { stack?: string }): Promise<void>
849+
function mark(name: string, options?: { stack?: string; kind?: BrowserTraceEntryKind }): Promise<void>
850850
```
851851

852852
Adds a named marker to the trace timeline and uses the current locator as marker context.
853853

854854
Pass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location.
855855

856+
Pass `options.kind` to categorize your marker as specific type, for example as `'action'`.
857+
856858
```ts
857859
import { page } from 'vitest/browser'
858860

‎packages/browser/context.d.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,20 @@ export interface ScreenshotOptions extends SelectorOptions {
4242
save?: boolean
4343
}
4444

45+
export type BrowserTraceEntryKind = 'action' | 'expect' | 'mark' | 'lifecycle'
46+
4547
export interface MarkOptions {
4648
/**
4749
* Optional stack string used to resolve marker location.
4850
* Useful for wrapper libraries that need to forward the end-user callsite.
4951
*/
5052
stack?: string
53+
54+
/**
55+
* Optional marker kind that's used to categorize the marker in the trace viewer.
56+
* @default 'mark'
57+
*/
58+
kind?: BrowserTraceEntryKind
5159
}
5260

5361
interface StandardScreenshotComparators {

‎packages/browser/src/client/tester/context.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ export const page: BrowserPage = {
391391
// TODO: support nested trace
392392
recordBrowserTraceEntry(currentTest, {
393393
name,
394-
kind: 'mark',
394+
kind: options?.kind ?? 'mark',
395395
status,
396396
startTime,
397397
duration: now() - startTime,
@@ -413,7 +413,7 @@ export const page: BrowserPage = {
413413
if (hasActiveTraceView) {
414414
recordBrowserTraceEntry(currentTest, {
415415
name,
416-
kind: 'mark',
416+
kind: bodyOrOptions?.kind ?? 'mark',
417417
stack: bodyOrOptions?.stack ?? error?.stack,
418418
})
419419
}

‎packages/browser/src/client/tester/locators.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ export abstract class Locator {
222222
if (hasActiveTraceView) {
223223
recordBrowserTraceEntry(currentTest, {
224224
name,
225-
kind: 'mark',
225+
kind: options?.kind ?? 'mark',
226226
element: this.serialize(),
227227
stack: options?.stack ?? error?.stack,
228228
})

‎packages/browser/src/client/tester/trace.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Task } from '@vitest/runner'
2+
import type { BrowserTraceEntryKind } from 'vitest/browser'
23
import type { SerializedLocator } from './locators'
34
import { getBrowserState, now } from '../utils'
45

@@ -9,7 +10,6 @@ export interface BrowserTraceData {
910
entries: BrowserTraceEntry[]
1011
}
1112

12-
export type BrowserTraceEntryKind = 'action' | 'expect' | 'mark' | 'lifecycle'
1313
export type BrowserTraceEntryStatus = 'pass' | 'fail'
1414
export type BrowserTraceSelectorResolution = 'matched' | 'missing' | 'error'
1515

‎packages/ui/client/components/trace/TraceView.vue‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ function formatTraceTiming(step: BrowserTraceEntry) {
122122
}
123123
124124
function formatStepName(step: BrowserTraceEntry) {
125-
if (step.kind === 'lifecycle' && step.name === 'vitest:onAfterRetryTask') {
125+
if (step.name === 'vitest:onAfterRetryTask') {
126126
return 'test finished'
127127
}
128-
if (step.kind === 'action' && step.name.startsWith('vitest:')) {
128+
if (step.name.startsWith('vitest:')) {
129129
return step.name.slice('vitest:'.length)
130130
}
131131
return step.name

‎test/browser/fixtures/trace/mark.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,12 @@ test('mark function', async () => {
3535
document.body.innerHTML = '<button>Hello</button>'
3636
})
3737
})
38+
39+
test('kind', async () => {
40+
document.body.innerHTML = '<button>Hello</button>'
41+
42+
await page.mark('action marker', { kind: 'action' })
43+
await page.mark('expect marker', { kind: 'expect' })
44+
await page.mark('lifecycle group', { kind: 'lifecycle' })
45+
await page.mark('lifecycle group', { kind: 'mark' })
46+
})

‎test/browser/specs/trace.test.ts‎

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ test('trace view artifacts', async () => {
100100
},
101101
"mark.test.ts": {
102102
"helper": "passed",
103+
"kind": "passed",
103104
"locator.mark": "passed",
104105
"mark function": "passed",
105106
"page.mark": "passed",
@@ -377,6 +378,43 @@ test('trace view artifacts', async () => {
377378
],
378379
},
379380
],
381+
"kind": [
382+
{
383+
"entries": [
384+
{
385+
"kind": "action",
386+
"location": "mark.test.ts:42",
387+
"name": "action marker",
388+
"snapshot": {},
389+
},
390+
{
391+
"kind": "expect",
392+
"location": "mark.test.ts:43",
393+
"name": "expect marker",
394+
"snapshot": {},
395+
},
396+
{
397+
"kind": "lifecycle",
398+
"location": "mark.test.ts:44",
399+
"name": "lifecycle group",
400+
"snapshot": {},
401+
},
402+
{
403+
"kind": "mark",
404+
"location": "mark.test.ts:45",
405+
"name": "lifecycle group",
406+
"snapshot": {},
407+
},
408+
{
409+
"kind": "lifecycle",
410+
"location": "mark.test.ts:39",
411+
"name": "vitest:onAfterRetryTask",
412+
"snapshot": {},
413+
"status": "pass",
414+
},
415+
],
416+
},
417+
],
380418
"locator.mark": [
381419
{
382420
"entries": [
@@ -1430,6 +1468,43 @@ test('trace view artifacts', async () => {
14301468
],
14311469
},
14321470
],
1471+
"kind": [
1472+
{
1473+
"entries": [
1474+
{
1475+
"kind": "action",
1476+
"location": "mark.test.ts:42",
1477+
"name": "action marker",
1478+
"snapshot": {},
1479+
},
1480+
{
1481+
"kind": "expect",
1482+
"location": "mark.test.ts:43",
1483+
"name": "expect marker",
1484+
"snapshot": {},
1485+
},
1486+
{
1487+
"kind": "lifecycle",
1488+
"location": "mark.test.ts:44",
1489+
"name": "lifecycle group",
1490+
"snapshot": {},
1491+
},
1492+
{
1493+
"kind": "mark",
1494+
"location": "mark.test.ts:45",
1495+
"name": "lifecycle group",
1496+
"snapshot": {},
1497+
},
1498+
{
1499+
"kind": "lifecycle",
1500+
"location": "mark.test.ts:39",
1501+
"name": "vitest:onAfterRetryTask",
1502+
"snapshot": {},
1503+
"status": "pass",
1504+
},
1505+
],
1506+
},
1507+
],
14331508
"locator.mark": [
14341509
{
14351510
"entries": [

0 commit comments

Comments
 (0)