diff --git a/code/addons/vitest/src/plugin/setup-file.test.ts b/code/addons/vitest/src/plugin/setup-file.test.ts new file mode 100644 index 00000000000..35720515074 --- /dev/null +++ b/code/addons/vitest/src/plugin/setup-file.test.ts @@ -0,0 +1,80 @@ +/* eslint-disable no-underscore-dangle */ +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +import { type Task, modifyErrorMessage } from './setup-file'; + +describe('modifyErrorMessage', () => { + const originalUrl = import.meta.env.__STORYBOOK_URL__; + beforeEach(() => { + import.meta.env.__STORYBOOK_URL__ = 'http://localhost:6006'; + }); + + afterEach(() => { + import.meta.env.__STORYBOOK_URL__ = originalUrl; + }); + + it('should modify the error message if the test is failing and there is a storyId in the task meta', () => { + const task: Task = { + type: 'test', + result: { + state: 'fail', + errors: [{ message: 'Original error message' }], + }, + meta: { storyId: 'my-story' }, + }; + + modifyErrorMessage({ task }); + + expect(task.result?.errors?.[0].message).toMatchInlineSnapshot(` + " + Click to debug the error directly in Storybook: http://localhost:6006/?path=/story/my-story&addonPanel=storybook/interactions/panel + + Original error message" + `); + expect(task.result?.errors?.[0].message).toContain('Original error message'); + }); + + it('should not modify the error message if task type is not "test"', () => { + const task: Task = { + type: 'custom', + result: { + state: 'fail', + errors: [{ message: 'Original error message' }], + }, + meta: { storyId: 'my-story' }, + }; + + modifyErrorMessage({ task }); + + expect(task.result?.errors?.[0].message).toBe('Original error message'); + }); + + it('should not modify the error message if task result state is not "fail"', () => { + const task: Task = { + type: 'test', + result: { + state: 'pass', + }, + meta: { storyId: 'my-story' }, + }; + + modifyErrorMessage({ task }); + + expect(task.result?.errors).toBeUndefined(); + }); + + it('should not modify the error message if meta.storyId is not present', () => { + const task: Task = { + type: 'test', + result: { + state: 'fail', + errors: [{ message: 'Non story test failure' }], + }, + meta: {}, + }; + + modifyErrorMessage({ task }); + + expect(task.result?.errors?.[0].message).toBe('Non story test failure'); + }); +}); diff --git a/code/addons/vitest/src/plugin/setup-file.ts b/code/addons/vitest/src/plugin/setup-file.ts index fb5bd5d9627..ad3db380712 100644 --- a/code/addons/vitest/src/plugin/setup-file.ts +++ b/code/addons/vitest/src/plugin/setup-file.ts @@ -2,7 +2,7 @@ /* eslint-disable no-underscore-dangle */ import { afterEach, vi } from 'vitest'; -import type { RunnerTask, TaskMeta } from 'vitest'; +import type { RunnerTask } from 'vitest'; import { Channel } from 'storybook/internal/channels'; @@ -13,13 +13,15 @@ declare global { var __STORYBOOK_ADDONS_CHANNEL__: Channel; } -type ExtendedMeta = TaskMeta & { storyId: string; hasPlayFunction: boolean }; +export type Task = Partial & { + meta: Record; +}; const transport = { setHandler: vi.fn(), send: vi.fn() }; -globalThis.__STORYBOOK_ADDONS_CHANNEL__ = new Channel({ transport }); +globalThis.__STORYBOOK_ADDONS_CHANNEL__ ??= new Channel({ transport }); -const modifyErrorMessage = ({ task }: { task: RunnerTask }) => { - const meta = task.meta as ExtendedMeta; +export const modifyErrorMessage = ({ task }: { task: Task }) => { + const meta = task.meta; if ( task.type === 'test' && task.result?.state === 'fail' &&