-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
Addon-Vitest: Extra changes for Vitest 4 #32600
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
Changes from all commits
d236c85
8071359
ad8d67f
423d58b
9f996c3
10aba50
2e5c563
514e6d5
f155516
a97e3b5
87a2680
8bd56d2
d7fbb48
10e8b3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from '@vitest/browser/context'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| // eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
| // @ts-ignore (vitest/browser is vitest 4 only, and we're using vitest 3 locally) | ||
| export * from 'vitest/browser'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import semver from 'semver'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Replace version sniffing with feature detection to improve robustness. The current approach uses JSON import attributes and semver to detect Vitest version, but this has several drawbacks:
A previous review comment suggested using feature detection instead, which is more robust and eliminates the semver dependency. Apply the feature detection approach suggested in the prior review: -import semver from 'semver';
-
type VitestBrowserContext = typeof import('@vitest/browser/context');
type VitestServerContext = VitestBrowserContext & {
server: {
commands: typeof import('@vitest/browser/context').server.commands & {
getInitialGlobals: () => Promise<Record<string, any>>;
};
};
};
-/** Gets the Vitest browser context based on which version of Vitest is installed. */
+/** Gets the Vitest browser context by feature detection (v4 first, then v3). */
export const getVitestBrowserContext = async (): Promise<VitestServerContext> => {
- const vitestVersion = await import('vitest/package.json', { with: { type: 'json' } }).then(
- (v) => v.version
- );
-
- if (semver.major(vitestVersion) >= 4) {
- return import('vitest/browser') as unknown as Promise<VitestServerContext>;
+ try {
+ return (await import('vitest/browser')) as unknown as VitestServerContext;
+ } catch {
+ return (await import('@vitest/browser/context')) as unknown as VitestServerContext;
}
-
- return import('@vitest/browser/context') as Promise<VitestServerContext>;
};Optionally, add caching to avoid repeated dynamic imports: let _ctxPromise: Promise<VitestServerContext> | undefined;
export const getVitestBrowserContext = async (): Promise<VitestServerContext> => {
if (_ctxPromise) return _ctxPromise;
_ctxPromise = (async () => {
try {
return (await import('vitest/browser')) as unknown as VitestServerContext;
} catch {
return (await import('@vitest/browser/context')) as unknown as VitestServerContext;
}
})();
return _ctxPromise;
};Also applies to: 15-20 🤖 Prompt for AI Agents |
||
|
|
||
| type VitestBrowserContext = typeof import('@vitest/browser/context'); | ||
|
|
||
| type VitestServerContext = VitestBrowserContext & { | ||
| server: { | ||
| commands: typeof import('@vitest/browser/context').server.commands & { | ||
| getInitialGlobals: () => Promise<Record<string, any>>; | ||
| }; | ||
| }; | ||
| }; | ||
|
|
||
| /** Gets the Vitest browser context based on which version of Vitest is installed. */ | ||
| export const getVitestBrowserContext = async (): Promise<VitestServerContext> => { | ||
| const vitestVersion = await import('vitest/package.json', { with: { type: 'json' } }).then( | ||
| (v) => v.version | ||
| ); | ||
|
|
||
| if (semver.major(vitestVersion) >= 4) { | ||
| // eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
| // @ts-ignore (vitest/browser is vitest 4 only, and we're using vitest 3 locally) | ||
| return import('vitest/browser') as unknown as Promise<VitestServerContext>; | ||
| } | ||
|
|
||
| return import('@vitest/browser/context') as Promise<VitestServerContext>; | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify runtime alias resolution and consider adding error handling.
The dynamic import relies on the vitest plugin to resolve the
'@storybook/addon-vitest/internal/vitest-context'alias at runtime. If the alias is not properly configured or the imported module doesn't match the expectedVitestBrowserContextshape, the type assertion will fail silently, leading to unclear runtime errors when accessingserver.commands.Run the following script to verify that the vitest plugin properly sets up this alias:
Consider adding runtime error handling to provide clearer error messages if the import fails:
🏁 Script executed:
Length of output: 3824
🏁 Script executed:
Length of output: 3703
🏁 Script executed:
Length of output: 5022
Add error handling and verify vitest-context.ts exports destructurable members for Vitest 4+ compatibility.
The dynamic import relies on
@storybook/addon-vitest/internal/vitest-contextexporting aserverproperty, butvitest-context.ts(Vitest 4+ path) only exports a named functiongetVitestBrowserContextand does not re-export destructurable members likevitest-context-legacy.tsdoes. This will cause a runtime error when test-utils.ts attempts to destructure{ server }on Vitest 4+.The pattern shown in
viewports.tswith error handling demonstrates the appropriate defensive approach:Alternatively, ensure
vitest-context.tsre-exports the required members likevitest-context-legacy.tsdoes by addingexport * from 'vitest/browser';.🤖 Prompt for AI Agents