Skip to content
Open
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
1 change: 0 additions & 1 deletion packages/browser/src/client/tester/tester-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ export class CommandsManager {
const rpc = state.rpc as any as BrowserRPC
const { sessionId, traces } = getBrowserState()
const filepath = state.filepath || state.current?.file?.filepath
args = args.filter(arg => arg !== undefined) // remove optional fields

const actionTraceGroupName = ACTION_TRACE_COMMANDS.has(command)
? `vitest:${command.slice('__vitest_'.length)}`
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/node/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ export function setupBrowserRpc(globalServer: ParentBrowserProject, defaultMocke
}
},
async triggerCommand(sessionId, command, testPath, payload) {
payload = payload.map(value => value === null ? undefined : value)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is not where the fix should be. We should fix the serialisation instead (serialise/deserialise that we pass to birpc)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The serialization and deserialization is implemented in rpc.ts. I found that the serialization used functions from a package name "flatted". In order to achieve what we want, those functions need to be reimplemented.
Screenshot 2026-08-20 at 11 16 06 AM

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, both stringify and parse accept a custom serializer. We could maybe provide a "hidden" value like "__VITEST_UNDEFINED__" to transform into undefined? Although I thought that flatted already supports undefined 🤔

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Will look into that and find a way to fix!

debug?.('[%s] Triggering command "%s"', sessionId, command)
const provider = project.browser!.provider
if (!provider) {
Expand Down
36 changes: 28 additions & 8 deletions test/browser/test/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,39 @@ it('can manipulate files', async () => {
})

it('can run custom commands', async () => {
const result = await myCustomCommand('arg1', 'arg2')
expect(result).toEqual({
testPath: expect.stringMatching('test/browser/test/commands.test.ts'),
arg1: 'arg1',
arg2: 'arg2',
})
{
const result = await myCustomCommand('arg1', 'arg2')
expect(result).toEqual({
testPath: expect.stringMatching('test/browser/test/commands.test.ts'),
arg1: 'arg1',
arg2: 'arg2',
})
}

{
const result = await myCustomCommand(undefined, 'arg2')
expect(result).toEqual({
testPath: expect.stringMatching('test/browser/test/commands.test.ts'),
arg1: undefined,
arg2: 'arg2',
})
}

{
const result = await myCustomCommand(null, 'arg2')
expect(result).toEqual({
testPath: expect.stringMatching('test/browser/test/commands.test.ts'),
arg1: null,
arg2: 'arg2',
})
}
})

declare module 'vitest/browser' {
interface BrowserCommands {
myCustomCommand: (arg1: string, arg2: string) => Promise<{
myCustomCommand: (arg1: string | undefined | null, arg2: string) => Promise<{
testPath: string
arg1: string
arg1: string | undefined | null
arg2: string
}>

Expand Down
Loading