From f45a96392c22e9b772382f1bc8b99b0e30520681 Mon Sep 17 00:00:00 2001 From: SpookyJelly <74237436+SpookyJelly@users.noreply.github.com> Date: Fri, 19 May 2023 12:18:44 +0900 Subject: [PATCH 001/524] fix: error on using useStoryPrepared hook sometimes, `api.getData` returns undefined. which is used by isPrepared. I added a exception for this --- code/lib/manager-api/src/modules/stories.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/code/lib/manager-api/src/modules/stories.ts b/code/lib/manager-api/src/modules/stories.ts index 0d8b7b87659c..a3d0f9e922ed 100644 --- a/code/lib/manager-api/src/modules/stories.ts +++ b/code/lib/manager-api/src/modules/stories.ts @@ -141,6 +141,7 @@ export const init: ModuleFn = ({ }, isPrepared: (storyId, refId) => { const data = api.getData(storyId, refId); + if(!data) return false; return data.type === 'story' ? data.prepared : true; }, resolveStory: (storyId, refId) => { From c68aa57cc47b713413b4b4901ed942d945c39564 Mon Sep 17 00:00:00 2001 From: SpookyJelly <74237436+SpookyJelly@users.noreply.github.com> Date: Tue, 23 May 2023 12:56:41 +0900 Subject: [PATCH 002/524] Update stories.ts Fixed a wrong lint. --- code/lib/manager-api/src/modules/stories.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/lib/manager-api/src/modules/stories.ts b/code/lib/manager-api/src/modules/stories.ts index a3d0f9e922ed..b7dd4bdadc50 100644 --- a/code/lib/manager-api/src/modules/stories.ts +++ b/code/lib/manager-api/src/modules/stories.ts @@ -141,7 +141,9 @@ export const init: ModuleFn = ({ }, isPrepared: (storyId, refId) => { const data = api.getData(storyId, refId); - if(!data) return false; + if(!data) { + return false; + } return data.type === 'story' ? data.prepared : true; }, resolveStory: (storyId, refId) => { From 4f83e9dabb2673a3d59e376a0bb8944c7379fc94 Mon Sep 17 00:00:00 2001 From: DiamondeX Date: Mon, 17 Jul 2023 19:53:16 +0200 Subject: [PATCH 003/524] Update controls.md The proposed changes eliminate the misleading assumption that this functionality can be used for control types other than `color` and `date` --- docs/essentials/controls.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/essentials/controls.md b/docs/essentials/controls.md index 5266c0760f02..cee93fa1816c 100644 --- a/docs/essentials/controls.md +++ b/docs/essentials/controls.md @@ -101,9 +101,9 @@ This replaces the input with a radio group for a more intuitive experience. ## Custom control type matchers -For a few types, Controls can automatically be inferred with [regex](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp). If you've used the Storybook CLI to setup your project it should have automatically created the following defaults in `.storybook/preview.js`: +Controls can automatically be inferred from arg's name with [regex](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp), but currently only for the color picker and date picker controls. If you've used the Storybook CLI to setup your project it should have automatically created the following defaults in `.storybook/preview.js`: -| Data type | Default regex | Description | +| Control | Default regex | Description | | :-------: | :--------------------------------------: | :-------------------------------------------------------: | | **color** | /(background|color)$/i | Will display a color picker UI for the args that match it | | **date** | `/Date$/` | Will display a date picker UI for the args that match it | From e4fbacfb7d492eb4e8432614d67d43edf732cb1e Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 19 Jul 2023 09:48:20 +0200 Subject: [PATCH 004/524] fix formatting --- code/lib/manager-api/src/modules/stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/manager-api/src/modules/stories.ts b/code/lib/manager-api/src/modules/stories.ts index b7dd4bdadc50..a62bb7b3aef7 100644 --- a/code/lib/manager-api/src/modules/stories.ts +++ b/code/lib/manager-api/src/modules/stories.ts @@ -141,7 +141,7 @@ export const init: ModuleFn = ({ }, isPrepared: (storyId, refId) => { const data = api.getData(storyId, refId); - if(!data) { + if (!data) { return false; } return data.type === 'story' ? data.prepared : true; From 79c2201b31031c37296d7791e65c29655b4aff87 Mon Sep 17 00:00:00 2001 From: Wilson Chen Date: Tue, 15 Aug 2023 13:47:19 -0700 Subject: [PATCH 005/524] Updated primary block to support of prop --- MIGRATION.md | 5 ++ code/ui/blocks/src/blocks/Primary.stories.tsx | 61 ++++++++++++++++++- code/ui/blocks/src/blocks/Primary.tsx | 51 ++++++++++++++-- docs/api/doc-block-primary.md | 6 ++ 4 files changed, 116 insertions(+), 7 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 5022eefb59bd..a5bc41380f8d 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -73,6 +73,7 @@ - [Unattached docs files](#unattached-docs-files) - [Doc Blocks](#doc-blocks) - [Meta block](#meta-block) + - [Primary block](#primary-block) - [Description block, `parameters.notes` and `parameters.info`](#description-block-parametersnotes-and-parametersinfo) - [Story block](#story-block) - [Source block](#source-block) @@ -1429,6 +1430,10 @@ Additionally to changing the docs information architecture, we've updated the AP The primary change of the `Meta` block is the ability to attach to CSF files with `` as described above. +##### Primary block + +The `Primary` block now also accepts an `of` prop as described above. It still accepts being passed `name` or no props at all. + ##### Description block, `parameters.notes` and `parameters.info` In 6.5 the Description doc block accepted a range of different props, `markdown`, `type` and `children` as a way to customize the content. diff --git a/code/ui/blocks/src/blocks/Primary.stories.tsx b/code/ui/blocks/src/blocks/Primary.stories.tsx index 42977ff6c9e3..b1d316c4e664 100644 --- a/code/ui/blocks/src/blocks/Primary.stories.tsx +++ b/code/ui/blocks/src/blocks/Primary.stories.tsx @@ -1,13 +1,16 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Primary } from './Primary'; +import * as DefaultButtonStories from '../examples/Button.stories'; +import * as StoriesParametersStories from '../examples/StoriesParameters.stories'; -const meta = { +const meta: Meta = { component: Primary, parameters: { + // workaround for https://github.com/storybookjs/storybook/issues/20505 + docs: { source: { type: 'code' } }, docsStyles: true, }, -} satisfies Meta; - +}; export default meta; type Story = StoryObj; @@ -22,3 +25,55 @@ export const WithoutToolbar: Story = { relativeCsfPaths: ['../examples/StoriesParameters.stories'], }, }; + +export const DefaultWithName: Story = { + name: 'Name', + args: { + name: 'Primary', + }, + parameters: { + relativeCsfPaths: ['../examples/Button.stories'], + }, +}; + +export const WithoutToolbarWithName: Story = { + name: 'Name Without Toolbar', + args: { + name: 'Without Toolbar', + }, + parameters: { + relativeCsfPaths: ['../examples/StoriesParameters.stories'], + }, +}; + +export const DefaultWithOf: Story = { + name: 'Of', + args: { + of: DefaultButtonStories, + }, + parameters: { relativeCsfPaths: ['../examples/Button.stories'] }, +}; + +export const WithoutToolbarWithOf: Story = { + name: 'Of Without Toolbar', + args: { + of: StoriesParametersStories, + }, + parameters: { relativeCsfPaths: ['../examples/StoriesParameters.stories'] }, +}; + +export const DefaultOfStringMetaAttached: Story = { + name: 'Of Attached "meta"', + args: { + of: 'meta', + }, + parameters: { relativeCsfPaths: ['../examples/Button.stories'] }, +}; + +export const WithoutToolbarOfStringMetaAttached: Story = { + name: 'Of Attached "meta" Without Toolbar', + args: { + of: 'meta', + }, + parameters: { relativeCsfPaths: ['../examples/StoriesParameters.stories'] }, +}; diff --git a/code/ui/blocks/src/blocks/Primary.tsx b/code/ui/blocks/src/blocks/Primary.tsx index 7583200f72c8..040edff489eb 100644 --- a/code/ui/blocks/src/blocks/Primary.tsx +++ b/code/ui/blocks/src/blocks/Primary.tsx @@ -2,7 +2,8 @@ import type { FC } from 'react'; import React, { useContext } from 'react'; import dedent from 'ts-dedent'; import { deprecate } from '@storybook/client-logger'; - +import type { Of } from './useOf'; +import { useOf } from './useOf'; import { DocsContext } from './DocsContext'; import { DocsStory } from './DocsStory'; @@ -11,17 +12,59 @@ interface PrimaryProps { * @deprecated Primary block should only be used to render the primary story, which is automatically found. */ name?: string; + /** + * Specify where to get the primary story from. + */ + of?: Of; } -export const Primary: FC = ({ name }) => { +const getPrimaryFromResolvedOf = (resolvedOf: ReturnType): any | null => { + switch (resolvedOf.type) { + case 'meta': { + return resolvedOf.csfFile.stories[0] || null; + } + case 'story': + case 'component': { + throw new Error( + `Unsupported module type. Primary's \`of\` prop only supports \`meta\`, got: ${ + (resolvedOf as any).type + }` + ); + } + default: { + throw new Error( + `Unrecognized module type resolved from 'useOf', got: ${(resolvedOf as any).type}` + ); + } + } +}; + +export const Primary: FC = (props) => { + const { name, of } = props; + + if ('of' in props && of === undefined) { + throw new Error('Unexpected `of={undefined}`, did you mistype a CSF file reference?'); + } + const docsContext = useContext(DocsContext); + + let story; + if (of) { + const resolvedOf = useOf(of || 'meta'); + story = getPrimaryFromResolvedOf(resolvedOf); + } + + if (!story) { + const storyId = name && docsContext.storyIdByName(name); + story = docsContext.storyById(storyId); + } + if (name) { deprecate(dedent`\`name\` prop is deprecated on the Primary block. The Primary block should only be used to render the primary story, which is automatically found. `); } - const storyId = name && docsContext.storyIdByName(name); - const story = docsContext.storyById(storyId); + return story ? ( ) : null; diff --git a/docs/api/doc-block-primary.md b/docs/api/doc-block-primary.md index 5d124df65b9f..37bf5eec9bc5 100644 --- a/docs/api/doc-block-primary.md +++ b/docs/api/doc-block-primary.md @@ -29,6 +29,12 @@ import { Primary } from '@storybook/blocks'; `Primary` is configured with the following props: +### `of` + +Type: CSF file exports + +Specifies the primary (first) story to be rendered. + ### `name` (⛔️ **Deprecated**) From f720962519e7298acf06f0ad4c8739afa84d4646 Mon Sep 17 00:00:00 2001 From: Wilson Chen Date: Tue, 15 Aug 2023 21:05:51 -0700 Subject: [PATCH 006/524] Removed use of any type --- code/ui/blocks/src/blocks/Primary.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/ui/blocks/src/blocks/Primary.tsx b/code/ui/blocks/src/blocks/Primary.tsx index 040edff489eb..7983ea94b0b7 100644 --- a/code/ui/blocks/src/blocks/Primary.tsx +++ b/code/ui/blocks/src/blocks/Primary.tsx @@ -18,12 +18,11 @@ interface PrimaryProps { of?: Of; } -const getPrimaryFromResolvedOf = (resolvedOf: ReturnType): any | null => { +const getPrimaryFromResolvedOf = (resolvedOf: ReturnType) => { switch (resolvedOf.type) { case 'meta': { return resolvedOf.csfFile.stories[0] || null; } - case 'story': case 'component': { throw new Error( `Unsupported module type. Primary's \`of\` prop only supports \`meta\`, got: ${ From d2c6faa1f9bfbd2a1635dd359c90498800df4f5a Mon Sep 17 00:00:00 2001 From: Wilson Chen Date: Thu, 24 Aug 2023 10:47:01 -0700 Subject: [PATCH 007/524] Revert back to satisfies operator for Primary, improve API docs --- code/ui/blocks/src/blocks/Primary.stories.tsx | 4 ++-- docs/api/doc-block-primary.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ui/blocks/src/blocks/Primary.stories.tsx b/code/ui/blocks/src/blocks/Primary.stories.tsx index b1d316c4e664..7c4747d53a3b 100644 --- a/code/ui/blocks/src/blocks/Primary.stories.tsx +++ b/code/ui/blocks/src/blocks/Primary.stories.tsx @@ -3,14 +3,14 @@ import { Primary } from './Primary'; import * as DefaultButtonStories from '../examples/Button.stories'; import * as StoriesParametersStories from '../examples/StoriesParameters.stories'; -const meta: Meta = { +const meta = { component: Primary, parameters: { // workaround for https://github.com/storybookjs/storybook/issues/20505 docs: { source: { type: 'code' } }, docsStyles: true, }, -}; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/docs/api/doc-block-primary.md b/docs/api/doc-block-primary.md index 37bf5eec9bc5..c4993c2db2a0 100644 --- a/docs/api/doc-block-primary.md +++ b/docs/api/doc-block-primary.md @@ -33,7 +33,7 @@ import { Primary } from '@storybook/blocks'; Type: CSF file exports -Specifies the primary (first) story to be rendered. +Specifies which CSF file is used to find the first story, which is then rendered by this block. Pass the full set of exports from the CSF file (not the default export!). ### `name` From fdba40fc4383006681a1001f32ce2aa897421e76 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 25 Aug 2023 13:31:43 +0200 Subject: [PATCH 008/524] add deprecation notice for cjs+vite --- MIGRATION.md | 21 ++++++++++++++++----- code/lib/core-server/src/build-dev.ts | 13 +++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 5022eefb59bd..d612b131e630 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,5 +1,7 @@

Migration

+- [From version 7.3.0 to 7.4.0](#from-version-730-to-740) + - [CommonJS with Vite is deprecated](#commonjs-with-vite-is-deprecated) - [From version 7.0.0 to 7.2.0](#from-version-700-to-720) - [Addon API is more type-strict](#addon-api-is-more-type-strict) - [From version 6.5.x to 7.0.0](#from-version-65x-to-700) @@ -302,6 +304,14 @@ - [Packages renaming](#packages-renaming) - [Deprecated embedded addons](#deprecated-embedded-addons) +## From version 7.3.0 to 7.4.0 + +#### CommonJS with Vite is deprecated + +Using CommonJS in the `main` configuration with `main.cjs` or `main.cts` is deprecated, and will be removed in Storybook 8.0. This is a necessary change because Vite will remove support for CommonJS in the upcoming v5 release. + +Rename your `main` configuration file to `main.js` or `main.ts` and refactor any CommonJS syntax - like `require()` or `module.exports` - to ESM. + ## From version 7.0.0 to 7.2.0 #### Addon API is more type-strict @@ -311,6 +321,7 @@ When registering an addon using `@storybook/manager-api`, the addon API is now m The `type` property is now a required field, and the `id` property should not be set anymore. Here's a correct example: + ```tsx import { addons, types } from '@storybook/manager-api'; @@ -318,7 +329,7 @@ addons.register('my-addon', () => { addons.add('my-addon/panel', { type: types.PANEL, title: 'My Addon', - render: ({ active }) => active ?
Hello World
: null, + render: ({ active }) => (active ?
Hello World
: null), }); }); ``` @@ -869,16 +880,16 @@ Given the following `main.js`: ```js export default { - stories: ['../**/*.stories.*'] -} + stories: ['../**/*.stories.*'], +}; ``` If you want to restore the previous behavior to include `node_modules`, you can update it to: ```js export default { - stories: ['../**/*.stories.*', '../**/node_modules/**/*.stories.*'] -} + stories: ['../**/*.stories.*', '../**/node_modules/**/*.stories.*'], +}; ``` The first glob would have node_modules automatically excluded by Storybook, and the second glob would include all stories that are under a nested `node_modules` directory. diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index 7785afdee7b7..f557161703e2 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -11,6 +11,7 @@ import { loadMainConfig, resolveAddonName, resolvePathInStorybookCache, + serverResolve, validateFrameworkName, } from '@storybook/core-common'; import prompts from 'prompts'; @@ -19,6 +20,8 @@ import { global } from '@storybook/global'; import { telemetry } from '@storybook/telemetry'; import { join, resolve } from 'path'; +import { deprecate } from '@storybook/node-logger'; +import dedent from 'ts-dedent'; import { storybookDevServer } from './dev-server'; import { outputStats } from './utils/output-stats'; import { outputStartupInformation } from './utils/output-startup-information'; @@ -102,6 +105,16 @@ export async function buildDevStandalone( getManagerBuilder(), ]); + if (builderName.includes('builder-vite')) { + const mainJsPath = serverResolve(resolve(options.configDir || '.storybook', 'main')) as string; + if (/\.c[jt]s$/.test(mainJsPath)) { + deprecate( + dedent(`Using the .cjs or .cts extension for your main config file is deprecated with Vite. + - Refer to the migration guide at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#commonjs-with-vite-is-deprecated`) + ); + } + } + const resolvedRenderer = renderer && resolveAddonName(options.configDir, renderer, options); // Load second pass: all presets are applied in order From 4cbcd333fe553dabec8d4cce267531c58b2104b6 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 25 Aug 2023 23:42:14 +0200 Subject: [PATCH 009/524] Improve CJS Vite migration notes Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index d612b131e630..bd359a3da148 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -310,7 +310,7 @@ Using CommonJS in the `main` configuration with `main.cjs` or `main.cts` is deprecated, and will be removed in Storybook 8.0. This is a necessary change because Vite will remove support for CommonJS in the upcoming v5 release. -Rename your `main` configuration file to `main.js` or `main.ts` and refactor any CommonJS syntax - like `require()` or `module.exports` - to ESM. +You can address this by converting your `main` configuration file to ESM syntax and renaming it to `main.mjs` or `main.mts` if your project does not have `"type": "module"` in its `package.json`. To convert the config file to ESM you will need to replace any CommonJS syntax like `require()`, `module.exports`, or `__dirname`. If you haven't already, you may also consider adding `"type": "module"` to your package.json and converting your project to ESM. ## From version 7.0.0 to 7.2.0 From 30dd4baa1553ac6e71eb8c876151e15d0b188721 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 25 Aug 2023 23:44:11 +0200 Subject: [PATCH 010/524] link to vite discussion about ESM-only --- MIGRATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIGRATION.md b/MIGRATION.md index bd359a3da148..8d865ca30581 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -308,7 +308,7 @@ #### CommonJS with Vite is deprecated -Using CommonJS in the `main` configuration with `main.cjs` or `main.cts` is deprecated, and will be removed in Storybook 8.0. This is a necessary change because Vite will remove support for CommonJS in the upcoming v5 release. +Using CommonJS in the `main` configuration with `main.cjs` or `main.cts` is deprecated, and will be removed in Storybook 8.0. This is a necessary change because [Vite will remove support for CommonJS in an upcoming release](https://github.com/vitejs/vite/discussions/13928). You can address this by converting your `main` configuration file to ESM syntax and renaming it to `main.mjs` or `main.mts` if your project does not have `"type": "module"` in its `package.json`. To convert the config file to ESM you will need to replace any CommonJS syntax like `require()`, `module.exports`, or `__dirname`. If you haven't already, you may also consider adding `"type": "module"` to your package.json and converting your project to ESM. From d80f62c8def8943db786630517c3735b93427247 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 29 Aug 2023 10:01:14 +0200 Subject: [PATCH 011/524] Improve VIte+CJS deprecation wording --- code/lib/core-server/src/build-dev.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index f557161703e2..630c99a4d367 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -109,7 +109,7 @@ export async function buildDevStandalone( const mainJsPath = serverResolve(resolve(options.configDir || '.storybook', 'main')) as string; if (/\.c[jt]s$/.test(mainJsPath)) { deprecate( - dedent(`Using the .cjs or .cts extension for your main config file is deprecated with Vite. + dedent(`Using CommonJS in your main configuration file is deprecated with Vite." - Refer to the migration guide at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#commonjs-with-vite-is-deprecated`) ); } From a0e1c7386203be952dfc0da324e12ed37fc2a4ce Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Tue, 29 Aug 2023 13:13:22 +0200 Subject: [PATCH 012/524] show deprecation warning when main.js contains CommonJS syntax. --- code/lib/core-server/src/build-dev.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/code/lib/core-server/src/build-dev.ts b/code/lib/core-server/src/build-dev.ts index 630c99a4d367..f40e66cce79c 100644 --- a/code/lib/core-server/src/build-dev.ts +++ b/code/lib/core-server/src/build-dev.ts @@ -22,6 +22,7 @@ import { telemetry } from '@storybook/telemetry'; import { join, resolve } from 'path'; import { deprecate } from '@storybook/node-logger'; import dedent from 'ts-dedent'; +import { readFile } from 'fs-extra'; import { storybookDevServer } from './dev-server'; import { outputStats } from './utils/output-stats'; import { outputStartupInformation } from './utils/output-startup-information'; @@ -106,12 +107,20 @@ export async function buildDevStandalone( ]); if (builderName.includes('builder-vite')) { + const deprecationMessage = + dedent(`Using CommonJS in your main configuration file is deprecated with Vite. + - Refer to the migration guide at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#commonjs-with-vite-is-deprecated`); + const mainJsPath = serverResolve(resolve(options.configDir || '.storybook', 'main')) as string; if (/\.c[jt]s$/.test(mainJsPath)) { - deprecate( - dedent(`Using CommonJS in your main configuration file is deprecated with Vite." - - Refer to the migration guide at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#commonjs-with-vite-is-deprecated`) - ); + deprecate(deprecationMessage); + } + const mainJsContent = await readFile(mainJsPath, 'utf-8'); + // Regex that matches any CommonJS-specific syntax, stolen from Vite: https://github.com/vitejs/vite/blob/91a18c2f7da796ff8217417a4bf189ddda719895/packages/vite/src/node/ssr/ssrExternal.ts#L87 + const CJS_CONTENT_REGEX = + /\bmodule\.exports\b|\bexports[.[]|\brequire\s*\(|\bObject\.(?:defineProperty|defineProperties|assign)\s*\(\s*exports\b/; + if (CJS_CONTENT_REGEX.test(mainJsContent)) { + deprecate(deprecationMessage); } } From 28422c5de967099dedb9131470aa0477872f91d5 Mon Sep 17 00:00:00 2001 From: Rashid Shamloo Date: Sat, 9 Sep 2023 02:07:30 +0330 Subject: [PATCH 013/524] fix: added code to update store.settings.lastTrackedStoryId in api.selectStory() to enable keeping the current story active when navigating between sidebar and canvas on mobile --- code/lib/manager-api/src/modules/stories.ts | 4 ++++ code/lib/manager-api/src/tests/stories.test.ts | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/code/lib/manager-api/src/modules/stories.ts b/code/lib/manager-api/src/modules/stories.ts index aff85aabcea3..8283d35da6e5 100644 --- a/code/lib/manager-api/src/modules/stories.ts +++ b/code/lib/manager-api/src/modules/stories.ts @@ -412,6 +412,10 @@ export const init: ModuleFn = ({ if (!entry) throw new Error(`Unknown id or title: '${titleOrId}'`); + store.setState({ + settings: { ...store.getState().settings, lastTrackedStoryId: entry.id }, + }); + // We want to navigate to the first ancestor entry that is a leaf const leafEntry = api.findLeafEntry(hash, entry.id); const fullId = leafEntry.refId ? `${leafEntry.refId}_${leafEntry.id}` : leafEntry.id; diff --git a/code/lib/manager-api/src/tests/stories.test.ts b/code/lib/manager-api/src/tests/stories.test.ts index a93cd1df9a99..eac7861b53bb 100644 --- a/code/lib/manager-api/src/tests/stories.test.ts +++ b/code/lib/manager-api/src/tests/stories.test.ts @@ -895,6 +895,16 @@ describe('stories API', () => { api.selectStory('intro'); expect(navigate).toHaveBeenCalledWith('/docs/intro--docs'); }); + it('updates lastTrackedStoryId', () => { + const initialState = { path: '/story/a--1', storyId: 'a--1', viewMode: 'story' }; + const moduleArgs = createMockModuleArgs({ initialState }); + const { api } = initStories(moduleArgs as unknown as ModuleArgs); + const { store } = moduleArgs; + + api.setIndex({ v: 4, entries: navigationEntries }); + api.selectStory('a--1'); + expect(store.getState().settings.lastTrackedStoryId).toBe('a--1'); + }); describe('deprecated api', () => { it('allows navigating to a combination of title + name', () => { const initialState = { path: '/story/a--1', storyId: 'a--1', viewMode: 'story' }; From 29f8596e326a8ae6c501e965afd4dd8f87aa3f8a Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 17 Aug 2023 16:27:08 +0200 Subject: [PATCH 014/524] Create @storybook/test package --- code/addons/actions/src/addArgs.ts | 7 +- code/addons/actions/src/addArgsHelpers.ts | 31 +++ code/lib/test/jest.config.js | 7 + code/lib/test/package.json | 68 ++++++ code/lib/test/project.json | 6 + code/lib/test/src/index.ts | 32 +++ code/lib/test/tsconfig.json | 4 + code/yarn.lock | 242 +++++++++++++++++++++- 8 files changed, 390 insertions(+), 7 deletions(-) create mode 100644 code/lib/test/jest.config.js create mode 100644 code/lib/test/package.json create mode 100644 code/lib/test/project.json create mode 100644 code/lib/test/src/index.ts create mode 100644 code/lib/test/tsconfig.json diff --git a/code/addons/actions/src/addArgs.ts b/code/addons/actions/src/addArgs.ts index 5742bd8627c0..db14aee0ce3d 100644 --- a/code/addons/actions/src/addArgs.ts +++ b/code/addons/actions/src/addArgs.ts @@ -1,7 +1,12 @@ import type { ArgsEnhancer } from '@storybook/types'; -import { addActionsFromArgTypes, inferActionsFromArgTypesRegex } from './addArgsHelpers'; +import { + addActionsFromArgTypes, + attachActionsToFunctionMocks, + inferActionsFromArgTypesRegex, +} from './addArgsHelpers'; export const argsEnhancers: ArgsEnhancer[] = [ addActionsFromArgTypes, inferActionsFromArgTypesRegex, + attachActionsToFunctionMocks, ]; diff --git a/code/addons/actions/src/addArgsHelpers.ts b/code/addons/actions/src/addArgsHelpers.ts index 7f56922d3962..fd93bea6e6f0 100644 --- a/code/addons/actions/src/addArgsHelpers.ts +++ b/code/addons/actions/src/addArgsHelpers.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle,no-param-reassign */ import type { Args, Renderer, ArgsEnhancer } from '@storybook/types'; import { action } from './runtime/action'; @@ -61,3 +62,33 @@ export const addActionsFromArgTypes: ArgsEnhancer = (context) => { return acc; }, {} as Args); }; + +export const attachActionsToFunctionMocks: ArgsEnhancer = (context) => { + const { + initialArgs, + argTypes, + parameters: { actions }, + } = context; + if (actions?.disable || !argTypes) { + return {}; + } + + const argTypesWithAction = Object.entries(initialArgs).filter( + ([, value]) => + typeof value === 'function' && + '_isMockFunction' in value && + value._isMockFunction && + !value._actionAttached + ); + + return argTypesWithAction.reduce((acc, [key, value]) => { + const previous = value.getMockImplementation(); + value.mockImplementation((...args: unknown[]) => { + action(key)(...args); + return previous?.(...args); + }); + // this enhancer is being called multiple times + value._actionAttached = true; + return acc; + }, {} as Args); +}; diff --git a/code/lib/test/jest.config.js b/code/lib/test/jest.config.js new file mode 100644 index 000000000000..4396fbc7010d --- /dev/null +++ b/code/lib/test/jest.config.js @@ -0,0 +1,7 @@ +const path = require('path'); +const baseConfig = require('../../jest.config.browser'); + +module.exports = { + ...baseConfig, + displayName: __dirname.split(path.sep).slice(-2).join(path.posix.sep), +}; diff --git a/code/lib/test/package.json b/code/lib/test/package.json new file mode 100644 index 000000000000..92d9ed1995ea --- /dev/null +++ b/code/lib/test/package.json @@ -0,0 +1,68 @@ +{ + "name": "@storybook/test", + "version": "7.4.0-alpha.0", + "description": "", + "keywords": [ + "storybook" + ], + "homepage": "https://github.com/storybookjs/storybook/tree/next/code/lib/test", + "bugs": { + "url": "https://github.com/storybookjs/storybook/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/storybookjs/storybook.git", + "directory": "code/lib/test" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "license": "MIT", + "sideEffects": false, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "node": "./dist/index.js", + "require": "./dist/index.js", + "import": "./dist/index.mjs" + }, + "./package.json": "./package.json" + }, + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "files": [ + "dist/**/*", + "README.md", + "*.js", + "*.d.ts" + ], + "scripts": { + "check": "../../../scripts/prepare/check.ts", + "prep": "../../../scripts/prepare/bundle.ts" + }, + "dependencies": { + "@storybook/instrumenter": "workspace:^", + "@testing-library/jest-dom": "^6.0.0", + "@vitest/expect": "^0.34.2", + "@vitest/spy": "^0.34.1", + "chai": "^4.3.7", + "expect": "^29.6.2" + }, + "devDependencies": { + "@types/chai": "^4", + "@types/testing-library__jest-dom": "^6", + "type-fest": "~2.19", + "typescript": "~4.9.3" + }, + "publishConfig": { + "access": "public" + }, + "bundler": { + "entries": [ + "./src/index.ts" + ] + }, + "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17" +} diff --git a/code/lib/test/project.json b/code/lib/test/project.json new file mode 100644 index 000000000000..68c18c664fd3 --- /dev/null +++ b/code/lib/test/project.json @@ -0,0 +1,6 @@ +{ + "name": "@storybook/test", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "implicitDependencies": [], + "type": "library" +} diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts new file mode 100644 index 000000000000..4d44c09ba333 --- /dev/null +++ b/code/lib/test/src/index.ts @@ -0,0 +1,32 @@ +/* eslint-disable import/no-extraneous-dependencies,import/no-named-default */ +import { default as expectPatched } from '@storybook/expect'; +import { instrument } from '@storybook/instrumenter'; +import * as matchers from '@testing-library/jest-dom/matchers'; +import * as _mock from '@vitest/spy'; +export type * from '@vitest/spy'; + +export const { mock } = instrument({ mock: _mock }, { retain: true }); + +/** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + */ +export interface Expect extends Pick { + /** + * The `expect` function is used every time you want to test a value. + * You will rarely call `expect` by itself. + * + * @param actual The value to apply matchers against. + */ + (actual: T): jest.JestMatchersShape< + jest.Matchers, T>, + jest.Matchers, T> + >; +} + +expectPatched.extend(matchers); + +export const expect: Expect = instrument( + { expect: expectPatched }, + { intercept: (_method, path) => path[0] !== 'expect' } +).expect as unknown as Expect; diff --git a/code/lib/test/tsconfig.json b/code/lib/test/tsconfig.json new file mode 100644 index 000000000000..52d43eaaa9b9 --- /dev/null +++ b/code/lib/test/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*"] +} diff --git a/code/yarn.lock b/code/yarn.lock index a9ad7bd0ce70..284c1a3103d0 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -3570,6 +3570,15 @@ __metadata: languageName: node linkType: hard +"@jest/expect-utils@npm:^29.6.2": + version: 29.6.2 + resolution: "@jest/expect-utils@npm:29.6.2" + dependencies: + jest-get-type: ^29.4.3 + checksum: 9a8dd5197d7e2d7f25a697dcb26dcf1483c5a9eccd1637ebd95b6deded6dd6d7d5513ceb1295119cd979abfc78d814ed00ff118a752028adb6646231ee234086 + languageName: node + linkType: hard + "@jest/expect-utils@npm:^29.7.0": version: 29.7.0 resolution: "@jest/expect-utils@npm:29.7.0" @@ -3661,7 +3670,7 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:^29.4.3, @jest/schemas@npm:^29.6.3": +"@jest/schemas@npm:^29.4.3, @jest/schemas@npm:^29.6.0, @jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" dependencies: @@ -3754,7 +3763,7 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^29.6.3": +"@jest/types@npm:^29.6.1, @jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" dependencies: @@ -7148,7 +7157,7 @@ __metadata: languageName: node linkType: hard -"@storybook/instrumenter@workspace:*, @storybook/instrumenter@workspace:lib/instrumenter": +"@storybook/instrumenter@workspace:*, @storybook/instrumenter@workspace:^, @storybook/instrumenter@workspace:lib/instrumenter": version: 0.0.0-use.local resolution: "@storybook/instrumenter@workspace:lib/instrumenter" dependencies: @@ -8138,6 +8147,23 @@ __metadata: languageName: unknown linkType: soft +"@storybook/test@workspace:lib/test": + version: 0.0.0-use.local + resolution: "@storybook/test@workspace:lib/test" + dependencies: + "@storybook/instrumenter": "workspace:^" + "@testing-library/jest-dom": ^6.0.0 + "@types/chai": ^4 + "@types/testing-library__jest-dom": ^6 + "@vitest/expect": ^0.34.2 + "@vitest/spy": ^0.34.1 + chai: ^4.3.7 + expect: ^29.6.2 + type-fest: ~2.19 + typescript: ~4.9.3 + languageName: unknown + linkType: soft + "@storybook/testing-library@npm:next": version: 0.2.1-next.0 resolution: "@storybook/testing-library@npm:0.2.1-next.0" @@ -8959,6 +8985,13 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^4": + version: 4.3.5 + resolution: "@types/chai@npm:4.3.5" + checksum: 816b3081e067c6e332be313e2e9a518b117c9eac51201cac749de0d6fcf7cb3238d0def37690b6539b3a928bd87b2f5f777914248447889ebc6f630a0d00e0e5 + languageName: node + linkType: hard + "@types/cheerio@npm:^0.22.22": version: 0.22.32 resolution: "@types/cheerio@npm:0.22.32" @@ -9782,6 +9815,15 @@ __metadata: languageName: node linkType: hard +"@types/testing-library__jest-dom@npm:^6": + version: 6.0.0 + resolution: "@types/testing-library__jest-dom@npm:6.0.0" + dependencies: + "@testing-library/jest-dom": "*" + checksum: 824950dc82752ddb656fa7ca851bf454804332f7a7a8571231abfc3553902198c6b96de209bb3dd1f1a15ee6a269a1efa56866041f5692ee0129308772e658e0 + languageName: node + linkType: hard + "@types/tmp@npm:^0.2.3": version: 0.2.3 resolution: "@types/tmp@npm:0.2.3" @@ -10137,6 +10179,46 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:^0.34.2": + version: 0.34.2 + resolution: "@vitest/expect@npm:0.34.2" + dependencies: + "@vitest/spy": 0.34.2 + "@vitest/utils": 0.34.2 + chai: ^4.3.7 + checksum: 80119614a826996a36f861e7b41cc41771009e1c6d1fcfa5c024d9f5aba83c2731058dc6869fef31e29631c68bec939c8373c4905c0612e860829fca616b76dc + languageName: node + linkType: hard + +"@vitest/spy@npm:0.34.2": + version: 0.34.2 + resolution: "@vitest/spy@npm:0.34.2" + dependencies: + tinyspy: ^2.1.1 + checksum: 98fbcea189d917693321cfded1b11d80ea8f1c1f6c6332ccbacb365e68640c286ecce28b563bb0b786e807d57f9cdd62b845ecf92e88bf184b38034ee85e4c69 + languageName: node + linkType: hard + +"@vitest/spy@npm:^0.34.1": + version: 0.34.1 + resolution: "@vitest/spy@npm:0.34.1" + dependencies: + tinyspy: ^2.1.1 + checksum: ba554f34276df580613027785ab8ca02cfd31cb588b0c506341e9a4aa75e369eaaf9d991119aa11b28e4b66819e659a3dbb4afacf46b387daabad1072746358f + languageName: node + linkType: hard + +"@vitest/utils@npm:0.34.2": + version: 0.34.2 + resolution: "@vitest/utils@npm:0.34.2" + dependencies: + diff-sequences: ^29.4.3 + loupe: ^2.3.6 + pretty-format: ^29.5.0 + checksum: 2165cb513094e53e456e0c73d5e8f2726fb9f92768dc954bb82f89acf3f630ed8ba86f272fc01f074bcdf794f99b866f870a3a167afc40b65a9a3f4410ee8ddc + languageName: node + linkType: hard + "@volar/language-core@npm:1.10.1, @volar/language-core@npm:~1.10.0": version: 1.10.1 resolution: "@volar/language-core@npm:1.10.1" @@ -11462,6 +11544,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: 25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b + languageName: node + linkType: hard + "assign-symbols@npm:^1.0.0": version: 1.0.0 resolution: "assign-symbols@npm:1.0.0" @@ -12890,6 +12979,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.7": + version: 4.3.7 + resolution: "chai@npm:4.3.7" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.2 + deep-eql: ^4.1.2 + get-func-name: ^2.0.0 + loupe: ^2.3.1 + pathval: ^1.1.1 + type-detect: ^4.0.5 + checksum: a11c6b74ce2d5587c3db1f1e5bf32073876319d4c65ba4e574ca9b56ec93ebbc80765e1fa4af354553afbf7ed245fb54c45d69d350a7b850c4aaf9f1e01f950f + languageName: node + linkType: hard + "chalk@npm:4.1.0": version: 4.1.0 resolution: "chalk@npm:4.1.0" @@ -13017,6 +13121,13 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.2": + version: 1.0.2 + resolution: "check-error@npm:1.0.2" + checksum: c58ac4d6a92203209a61d025568198c073f101691eb6247f999266e1d1e3ab3af2bbe0a41af5008c1f1b95446ec7831e6ba91f03816177f2da852f316ad7921d + languageName: node + linkType: hard + "checkup@npm:^1.3.0": version: 1.3.0 resolution: "checkup@npm:1.3.0" @@ -14513,6 +14624,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.2": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: ^4.0.0 + checksum: ff34e8605d8253e1bf9fe48056e02c6f347b81d9b5df1c6650a1b0f6f847b4a86453b16dc226b34f853ef14b626e85d04e081b022e20b00cd7d54f079ce9bbdd + languageName: node + linkType: hard + "deep-equal@npm:^1.1.1": version: 1.1.1 resolution: "deep-equal@npm:1.1.1" @@ -14807,7 +14927,7 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": +"diff-sequences@npm:^29.4.3, diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" checksum: 32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 @@ -16686,6 +16806,20 @@ __metadata: languageName: node linkType: hard +"expect@npm:^29.6.2": + version: 29.6.2 + resolution: "expect@npm:29.6.2" + dependencies: + "@jest/expect-utils": ^29.6.2 + "@types/node": "*" + jest-get-type: ^29.4.3 + jest-matcher-utils: ^29.6.2 + jest-message-util: ^29.6.2 + jest-util: ^29.6.2 + checksum: c45d700947f23b8d5d034678733a35bdb404c3c1f26163ef692f9a05ae0b85b1918aea030ecf5efb7ffc61f5363593a57247483078187f2406736b5c9e6ceef9 + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.1 resolution: "exponential-backoff@npm:3.1.1" @@ -17766,6 +17900,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.0": + version: 2.0.0 + resolution: "get-func-name@npm:2.0.0" + checksum: ed8791f7ba92cfd747259dff7ec8b6cc42734cebd031fb58c99a6e71d24d3532d84b46ad7806cafad6ad21784dd04ae1808a002d2b21001425e21f5f394c34e7 + languageName: node + linkType: hard + "get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1": version: 1.2.1 resolution: "get-intrinsic@npm:1.2.1" @@ -20347,6 +20488,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-diff@npm:29.6.2" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^29.4.3 + jest-get-type: ^29.4.3 + pretty-format: ^29.6.2 + checksum: 341948de9fbbf9884a93e17a6ff638112109ca640420d62a26753329fdf1d6d0b4582a2a2e894cac4120dc8fb251361d58917288e9f1b955d286b78ab1db29c3 + languageName: node + linkType: hard + "jest-diff@npm:^29.7.0": version: 29.7.0 resolution: "jest-diff@npm:29.7.0" @@ -20423,7 +20576,7 @@ __metadata: languageName: node linkType: hard -"jest-get-type@npm:^29.6.3": +"jest-get-type@npm:^29.4.3, jest-get-type@npm:^29.6.3": version: 29.6.3 resolution: "jest-get-type@npm:29.6.3" checksum: 552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b @@ -20508,6 +20661,18 @@ __metadata: languageName: node linkType: hard +"jest-matcher-utils@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-matcher-utils@npm:29.6.2" + dependencies: + chalk: ^4.0.0 + jest-diff: ^29.6.2 + jest-get-type: ^29.4.3 + pretty-format: ^29.6.2 + checksum: 3b383753b8744431a7003c00749ee1ecb16ec4f2e23c8214a95a77e27687d4b3ddd0f4afec85fa5b4ee950c69452de35dc3f07a2da41ff5914dd04bf2decf79e + languageName: node + linkType: hard + "jest-matcher-utils@npm:^29.7.0": version: 29.7.0 resolution: "jest-matcher-utils@npm:29.7.0" @@ -20520,6 +20685,23 @@ __metadata: languageName: node linkType: hard +"jest-message-util@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-message-util@npm:29.6.2" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.6.1 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.6.2 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 4c5624ff281aa9ea09a7fca09f58b39282d3e452651d335d68834795e59c131f20d7fa174ebededa3399f1474af410c434c4dfdba57a99e3e8acf265fbb7c123 + languageName: node + linkType: hard + "jest-message-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-message-util@npm:29.7.0" @@ -20757,6 +20939,20 @@ __metadata: languageName: node linkType: hard +"jest-util@npm:^29.6.2": + version: 29.6.2 + resolution: "jest-util@npm:29.6.2" + dependencies: + "@jest/types": ^29.6.1 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 2510385dc2b828c5de89d1508984ab74edf010377e8a3664549eb1da74f96e8a1badd535b3b8da286c4e2ccfa9de4f07cb501f6c91dc7b5bc5618c248b2b2f0a + languageName: node + linkType: hard + "jest-validate@npm:^29.7.0": version: 29.7.0 resolution: "jest-validate@npm:29.7.0" @@ -22121,6 +22317,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.1, loupe@npm:^2.3.6": + version: 2.3.6 + resolution: "loupe@npm:2.3.6" + dependencies: + get-func-name: ^2.0.0 + checksum: a974841ce94ef2a35aac7144e7f9e789e3887f82286cd9ffe7ff00f2ac9d117481989948657465e2b0b102f23136d89ae0a18fd4a32d9015012cd64464453289 + languageName: node + linkType: hard + "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -25599,6 +25804,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc + languageName: node + linkType: hard + "pbkdf2@npm:^3.0.3": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" @@ -26211,6 +26423,17 @@ __metadata: languageName: node linkType: hard +"pretty-format@npm:^29.5.0, pretty-format@npm:^29.6.2": + version: 29.6.2 + resolution: "pretty-format@npm:29.6.2" + dependencies: + "@jest/schemas": ^29.6.0 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: fb9b404f61c48d1b9408ec93b9dbd0266c1fed36dc99c2ebaa42c1da2354f201a57862a28455ddb573e9b14e74cb8542928c0ef85955b7fd7e3e70ce42e52b32 + languageName: node + linkType: hard + "pretty-format@npm:^3.8.0": version: 3.8.0 resolution: "pretty-format@npm:3.8.0" @@ -30408,6 +30631,13 @@ __metadata: languageName: node linkType: hard +"tinyspy@npm:^2.1.1": + version: 2.1.1 + resolution: "tinyspy@npm:2.1.1" + checksum: 0e7186fd380cbc594c35a0f6270f61b79ed22d1d960cac6064c3a5ebcf8a3a70d6590ff2049cba1d58631c3c556b1a67896d0db136381da7855a37087a90fbc5 + languageName: node + linkType: hard + "tmp@npm:0.0.28": version: 0.0.28 resolution: "tmp@npm:0.0.28" @@ -30866,7 +31096,7 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8": +"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd From f0d68a1971f4d9b0f6705775f74681c6a18cabbc Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 25 Aug 2023 16:11:48 +0200 Subject: [PATCH 015/524] Replace expect (from jest) with @vitest/expect --- .../lib/instrumenter/src/instrumenter.test.ts | 38 +++++ code/lib/instrumenter/src/instrumenter.ts | 37 +++-- code/lib/instrumenter/src/types.ts | 1 + code/lib/test/src/expect.ts | 136 ++++++++++++++++++ code/lib/test/src/index.ts | 46 +++--- 5 files changed, 215 insertions(+), 43 deletions(-) create mode 100644 code/lib/test/src/expect.ts diff --git a/code/lib/instrumenter/src/instrumenter.test.ts b/code/lib/instrumenter/src/instrumenter.test.ts index eadb1f7d5c84..184c6773a747 100644 --- a/code/lib/instrumenter/src/instrumenter.test.ts +++ b/code/lib/instrumenter/src/instrumenter.test.ts @@ -112,6 +112,44 @@ describe('Instrumenter', () => { expect(result.fn1.fn2.__originalFn__).toBe(fn1.fn2); }); + it('patches functions correctly that reference this', () => { + const object = { + name: 'name', + method() { + return this.name; + }, + }; + + const instrumented = instrument(object); + expect(object.method()).toEqual(instrumented.method()); + + expect(instrumented.method).toEqual(expect.any(Function)); + expect(instrumented.method.__originalFn__).toBe(object.method); + }); + + it('patches functions correctly that use proxies', () => { + const object = new Proxy( + { + name: 'name', + method() { + return this.name; + }, + }, + { + get(target, prop, receiver) { + if (prop === 'name') return `${target[prop]}!`; + return Reflect.get(target, prop, receiver); + }, + } + ); + + const instrumented = instrument(object); + expect(object.method()).toEqual(instrumented.method()); + + expect(instrumented.method).toEqual(expect.any(Function)); + expect(instrumented.method.__originalFn__).toBe(object.method); + }); + it('patched functions call the original function when invoked', () => { const { fn } = instrument({ fn: jest.fn() }); const obj = {}; diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 357b9df52817..21f05a0ea585 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -24,8 +24,8 @@ export const EVENTS = { END: 'storybook/instrumenter/end', }; -type PatchedObj = { - [Property in keyof TObj]: TObj[Property] & { __originalFn__: PatchedObj }; +type PatchedObj> = { + [Property in keyof TObj]: TObj[Property] & { __originalFn__: TObj[Property] }; }; const controlsDisabled: ControlStates = { @@ -49,7 +49,6 @@ const isInstrumentable = (o: unknown) => { if (o.constructor === undefined) return true; const proto = o.constructor.prototype; if (!isObject(proto)) return false; - if (Object.prototype.hasOwnProperty.call(proto, 'isPrototypeOf') === false) return false; return true; }; @@ -290,11 +289,13 @@ export class Instrumenter { // Traverses the object structure to recursively patch all function properties. // Returns the original object, or a new object with the same constructor, // depending on whether it should mutate. - instrument(obj: TObj, options: Options): PatchedObj { - if (!isInstrumentable(obj)) return obj; + instrument>(obj: TObj, options: Options): PatchedObj { + if (!isInstrumentable(obj)) return obj as PatchedObj; const { mutate = false, path = [] } = options; - return Object.keys(obj).reduce( + + const keys = options.getKeys ? options.getKeys(obj) : Object.keys(obj); + return keys.reduce( (acc, key) => { const value = (obj as Record)[key]; @@ -305,13 +306,13 @@ export class Instrumenter { } // Already patched, so we pass through unchanged - if (typeof value.__originalFn__ === 'function') { + if ('__originalFn__' in value && typeof value.__originalFn__ === 'function') { acc[key] = value; return acc; } // Patch the function and mark it "patched" by adding a reference to the original function - acc[key] = (...args: any[]) => this.track(key, value, args, options); + acc[key] = (...args: any[]) => this.track(key, value, obj, args, options); acc[key].__originalFn__ = value; // Reuse the original name as the patched function's name @@ -334,7 +335,13 @@ export class Instrumenter { // Monkey patch an object method to record calls. // Returns a function that invokes the original function, records the invocation ("call") and // returns the original result. - track(method: string, fn: Function, args: any[], options: Options) { + track( + method: string, + fn: Function, + object: Record, + args: any[], + options: Options + ) { const storyId: StoryId = args?.[0]?.__storyId__ || global.__STORYBOOK_PREVIEW__?.selectionStore?.selection?.storyId; const { cursor, ancestors } = this.getState(storyId); @@ -344,11 +351,11 @@ export class Instrumenter { const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept; const call = { id, cursor, storyId, ancestors, path, method, args, interceptable, retain }; const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke; - const result = interceptOrInvoke.call(this, fn, call, options); + const result = interceptOrInvoke.call(this, fn, object, call, options); return this.instrument(result, { ...options, mutate: true, path: [{ __callId__: call.id }] }); } - intercept(fn: Function, call: Call, options: Options) { + intercept(fn: Function, object: Record, call: Call, options: Options) { const { chainedCallIds, isDebugging, playUntil } = this.getState(call.storyId); // For a "jump to step" action, continue playing until we hit a call by that ID. @@ -358,7 +365,7 @@ export class Instrumenter { if (playUntil === call.id) { this.setState(call.storyId, { playUntil: undefined }); } - return this.invoke(fn, call, options); + return this.invoke(fn, object, call, options); } // Instead of invoking the function, defer the function call until we continue playing. @@ -373,11 +380,11 @@ export class Instrumenter { const { [call.id]: _, ...resolvers } = state.resolvers; return { isLocked: true, resolvers }; }); - return this.invoke(fn, call, options); + return this.invoke(fn, object, call, options); }); } - invoke(fn: Function, call: Call, options: Options) { + invoke(fn: Function, object: Record, call: Call, options: Options) { // TODO this doesnt work because the abortSignal we have here is the newly created one // const { abortSignal } = global.window.__STORYBOOK_PREVIEW__ || {}; // if (abortSignal && abortSignal.aborted) throw IGNORED_EXCEPTION; @@ -510,7 +517,7 @@ export class Instrumenter { }; }); - const result = fn(...finalArgs); + const result = fn.apply(object, finalArgs); // Track the result so we can trace later uses of it back to the originating call. // Primitive results (undefined, null, boolean, string, number, BigInt) are ignored. diff --git a/code/lib/instrumenter/src/types.ts b/code/lib/instrumenter/src/types.ts index 1076d4dd3a1d..bfcfc42d1b45 100644 --- a/code/lib/instrumenter/src/types.ts +++ b/code/lib/instrumenter/src/types.ts @@ -90,4 +90,5 @@ export interface Options { mutate?: boolean; path?: Array; getArgs?: (call: Call, state: State) => Call['args']; + getKeys?: (originalObject: Record) => string[]; } diff --git a/code/lib/test/src/expect.ts b/code/lib/test/src/expect.ts new file mode 100644 index 000000000000..d9c63b2bbb8d --- /dev/null +++ b/code/lib/test/src/expect.ts @@ -0,0 +1,136 @@ +import * as chai from 'chai'; +import type { + AsymmetricMatchersContaining, + ExpectStatic, + JestAssertion, + MatchersObject, + MatcherState, +} from '@vitest/expect'; + +import { + getState, + GLOBAL_EXPECT, + JestAsymmetricMatchers, + JestChaiExpect, + JestExtend, + setState, +} from '@vitest/expect'; +import * as matchers from '@testing-library/jest-dom/matchers'; + +type Promisify = { + [K in keyof O]: O[K] extends (...args: infer A) => infer R + ? O extends R + ? Promisify + : (...args: A) => Promise + : O[K]; +}; + +// We only expose the jest compatible API for now +export interface Assertion extends Promisify> { + toHaveBeenCalledOnce(): Promise; + toSatisfy(matcher: (value: E) => boolean, message?: string): Promise; + resolves: Promisify>; + rejects: Promisify>; +} + +export interface Expect extends AsymmetricMatchersContaining { + (actual: T, message?: string): Assertion; + unreachable(message?: string): Promise; + soft(actual: T, message?: string): Assertion; + extend(expects: MatchersObject): void; + assertions(expected: number): Promise; + hasAssertions(): Promise; + anything(): any; + any(constructor: unknown): any; + getState(): MatcherState; + setState(state: Partial): void; + not: AsymmetricMatchersContaining; +} + +export function createExpect() { + chai.use(JestExtend); + chai.use(JestChaiExpect); + chai.use(JestAsymmetricMatchers); + + const expect = ((value: unknown, message?: string) => { + const { assertionCalls } = getState(expect); + setState({ assertionCalls: assertionCalls + 1, soft: false }, expect); + return chai.expect(value, message); + }) as ExpectStatic; + + Object.assign(expect, chai.expect); + + // The below methods are added to make chai jest compatible + + expect.getState = () => getState(expect); + expect.setState = (state) => setState(state as Partial, expect); + + // @ts-expect-error chai.extend is not typed + expect.extend = (expects: MatchersObject) => chai.expect.extend(expect, expects); + + expect.soft = (...args) => { + const assert = expect(...args); + expect.setState({ + soft: true, + }); + return assert; + }; + + expect.unreachable = (message?: string): never => { + chai.assert.fail(`expected${message ? ` "${message}" ` : ' '}not to be reached`); + }; + + function assertions(expected: number) { + const errorGen = () => + new Error( + `expected number of assertions to be ${expected}, but got ${ + expect.getState().assertionCalls + }` + ); + if (Error.captureStackTrace) Error.captureStackTrace(errorGen(), assertions); + + expect.setState({ + expectedAssertionsNumber: expected, + expectedAssertionsNumberErrorGen: errorGen, + }); + } + + function hasAssertions() { + const error = new Error('expected any number of assertion, but got none'); + if (Error.captureStackTrace) Error.captureStackTrace(error, hasAssertions); + + expect.setState({ + isExpectingAssertions: true, + isExpectingAssertionsError: error, + }); + } + + setState( + { + // this should also add "snapshotState" that is added conditionally + assertionCalls: 0, + isExpectingAssertions: false, + isExpectingAssertionsError: null, + expectedAssertionsNumber: null, + expectedAssertionsNumberErrorGen: null, + }, + expect + ); + + chai.util.addMethod(expect, 'assertions', assertions); + chai.util.addMethod(expect, 'hasAssertions', hasAssertions); + expect.extend(matchers); + + return expect as unknown as Expect; +} + +const expect = createExpect(); + +// @vitest/expect expects this to be set +Object.defineProperty(globalThis, GLOBAL_EXPECT, { + value: expect, + writable: true, + configurable: true, +}); + +export { expect }; diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 4d44c09ba333..2371206510bf 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -1,32 +1,22 @@ -/* eslint-disable import/no-extraneous-dependencies,import/no-named-default */ -import { default as expectPatched } from '@storybook/expect'; import { instrument } from '@storybook/instrumenter'; -import * as matchers from '@testing-library/jest-dom/matchers'; -import * as _mock from '@vitest/spy'; -export type * from '@vitest/spy'; +import * as spy from '@vitest/spy'; +import chai from 'chai'; +import { expect as rawExpect } from './expect'; -export const { mock } = instrument({ mock: _mock }, { retain: true }); +export * from '@vitest/spy'; -/** - * The `expect` function is used every time you want to test a value. - * You will rarely call `expect` by itself. - */ -export interface Expect extends Pick { - /** - * The `expect` function is used every time you want to test a value. - * You will rarely call `expect` by itself. - * - * @param actual The value to apply matchers against. - */ - (actual: T): jest.JestMatchersShape< - jest.Matchers, T>, - jest.Matchers, T> - >; -} +export const { fn } = instrument({ fn: spy.fn }, { retain: true }); -expectPatched.extend(matchers); - -export const expect: Expect = instrument( - { expect: expectPatched }, - { intercept: (_method, path) => path[0] !== 'expect' } -).expect as unknown as Expect; +export const { expect } = instrument( + { expect: rawExpect }, + { + getKeys: (obj) => { + const privateApi = ['assert', '__methods', '__flags']; + if (obj.constructor === chai.Assertion) { + return Object.keys(Object.getPrototypeOf(obj)).filter((it) => !privateApi.includes(it)); + } + return Object.keys(obj); + }, + intercept: true, + } +); From 97350aa59e0508974a5290f79b1b65f27e98fb7d Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 25 Aug 2023 16:48:20 +0200 Subject: [PATCH 016/524] Fix build --- code/lib/test/package.json | 1 - code/lib/test/src/index.ts | 2 +- code/yarn.lock | 144 ++++++++++++++++--------------------- 3 files changed, 63 insertions(+), 84 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 92d9ed1995ea..67cb6a46ea1f 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -52,7 +52,6 @@ }, "devDependencies": { "@types/chai": "^4", - "@types/testing-library__jest-dom": "^6", "type-fest": "~2.19", "typescript": "~4.9.3" }, diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 2371206510bf..cd6dc6167a13 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -10,7 +10,7 @@ export const { fn } = instrument({ fn: spy.fn }, { retain: true }); export const { expect } = instrument( { expect: rawExpect }, { - getKeys: (obj) => { + getKeys: (obj: Record) => { const privateApi = ['assert', '__methods', '__flags']; if (obj.constructor === chai.Assertion) { return Object.keys(Object.getPrototypeOf(obj)).filter((it) => !privateApi.includes(it)); diff --git a/code/yarn.lock b/code/yarn.lock index 284c1a3103d0..12aec53bd4eb 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -3570,12 +3570,12 @@ __metadata: languageName: node linkType: hard -"@jest/expect-utils@npm:^29.6.2": - version: 29.6.2 - resolution: "@jest/expect-utils@npm:29.6.2" +"@jest/expect-utils@npm:^29.6.4": + version: 29.6.4 + resolution: "@jest/expect-utils@npm:29.6.4" dependencies: - jest-get-type: ^29.4.3 - checksum: 9a8dd5197d7e2d7f25a697dcb26dcf1483c5a9eccd1637ebd95b6deded6dd6d7d5513ceb1295119cd979abfc78d814ed00ff118a752028adb6646231ee234086 + jest-get-type: ^29.6.3 + checksum: 17d87d551090f6b460fa45605c614b2ad28e257360a5b8152216fe983370f4cfb8482d2d017552c2be43be1caa0ff5594f1381be17798dcad3899e05b297fe83 languageName: node linkType: hard @@ -3670,7 +3670,7 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:^29.4.3, @jest/schemas@npm:^29.6.0, @jest/schemas@npm:^29.6.3": +"@jest/schemas@npm:^29.4.3, @jest/schemas@npm:^29.6.3": version: 29.6.3 resolution: "@jest/schemas@npm:29.6.3" dependencies: @@ -3763,7 +3763,7 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^29.6.1, @jest/types@npm:^29.6.3": +"@jest/types@npm:^29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" dependencies: @@ -8154,7 +8154,6 @@ __metadata: "@storybook/instrumenter": "workspace:^" "@testing-library/jest-dom": ^6.0.0 "@types/chai": ^4 - "@types/testing-library__jest-dom": ^6 "@vitest/expect": ^0.34.2 "@vitest/spy": ^0.34.1 chai: ^4.3.7 @@ -9815,15 +9814,6 @@ __metadata: languageName: node linkType: hard -"@types/testing-library__jest-dom@npm:^6": - version: 6.0.0 - resolution: "@types/testing-library__jest-dom@npm:6.0.0" - dependencies: - "@testing-library/jest-dom": "*" - checksum: 824950dc82752ddb656fa7ca851bf454804332f7a7a8571231abfc3553902198c6b96de209bb3dd1f1a15ee6a269a1efa56866041f5692ee0129308772e658e0 - languageName: node - linkType: hard - "@types/tmp@npm:^0.2.3": version: 0.2.3 resolution: "@types/tmp@npm:0.2.3" @@ -10180,42 +10170,33 @@ __metadata: linkType: hard "@vitest/expect@npm:^0.34.2": - version: 0.34.2 - resolution: "@vitest/expect@npm:0.34.2" + version: 0.34.3 + resolution: "@vitest/expect@npm:0.34.3" dependencies: - "@vitest/spy": 0.34.2 - "@vitest/utils": 0.34.2 + "@vitest/spy": 0.34.3 + "@vitest/utils": 0.34.3 chai: ^4.3.7 - checksum: 80119614a826996a36f861e7b41cc41771009e1c6d1fcfa5c024d9f5aba83c2731058dc6869fef31e29631c68bec939c8373c4905c0612e860829fca616b76dc + checksum: ec70fba265b5bbd31f9c06c60e504ee0f1394df0871a5bddbe0a6b0a2436705f5e41e183fcdec3dd8864b5432b14d4f3802b896ba625ae0a44b52a9a08ddbd73 languageName: node linkType: hard -"@vitest/spy@npm:0.34.2": - version: 0.34.2 - resolution: "@vitest/spy@npm:0.34.2" +"@vitest/spy@npm:0.34.3, @vitest/spy@npm:^0.34.1": + version: 0.34.3 + resolution: "@vitest/spy@npm:0.34.3" dependencies: tinyspy: ^2.1.1 - checksum: 98fbcea189d917693321cfded1b11d80ea8f1c1f6c6332ccbacb365e68640c286ecce28b563bb0b786e807d57f9cdd62b845ecf92e88bf184b38034ee85e4c69 + checksum: 8052386c56b55ebaca5ffbf5b91bb73c8c4e0e4ca1c53c922ed947703f54363689df5b4000718bbdc7c79c84e3fb4b788c42efdb8bb8592c44123bd717097f33 languageName: node linkType: hard -"@vitest/spy@npm:^0.34.1": - version: 0.34.1 - resolution: "@vitest/spy@npm:0.34.1" - dependencies: - tinyspy: ^2.1.1 - checksum: ba554f34276df580613027785ab8ca02cfd31cb588b0c506341e9a4aa75e369eaaf9d991119aa11b28e4b66819e659a3dbb4afacf46b387daabad1072746358f - languageName: node - linkType: hard - -"@vitest/utils@npm:0.34.2": - version: 0.34.2 - resolution: "@vitest/utils@npm:0.34.2" +"@vitest/utils@npm:0.34.3": + version: 0.34.3 + resolution: "@vitest/utils@npm:0.34.3" dependencies: diff-sequences: ^29.4.3 loupe: ^2.3.6 pretty-format: ^29.5.0 - checksum: 2165cb513094e53e456e0c73d5e8f2726fb9f92768dc954bb82f89acf3f630ed8ba86f272fc01f074bcdf794f99b866f870a3a167afc40b65a9a3f4410ee8ddc + checksum: 7ca2d82c4286b963b8d8004812464c81b42d73d027b739fa5b2f2cdfb2a14e409f8ad1da6c269ba7379c74a93bb0e81485b2040a18a06a886b49c4bef1e494ab languageName: node linkType: hard @@ -12980,8 +12961,8 @@ __metadata: linkType: hard "chai@npm:^4.3.7": - version: 4.3.7 - resolution: "chai@npm:4.3.7" + version: 4.3.8 + resolution: "chai@npm:4.3.8" dependencies: assertion-error: ^1.1.0 check-error: ^1.0.2 @@ -12990,7 +12971,7 @@ __metadata: loupe: ^2.3.1 pathval: ^1.1.1 type-detect: ^4.0.5 - checksum: a11c6b74ce2d5587c3db1f1e5bf32073876319d4c65ba4e574ca9b56ec93ebbc80765e1fa4af354553afbf7ed245fb54c45d69d350a7b850c4aaf9f1e01f950f + checksum: 5aa714fbbd4b3a1506f4fc9094851bf9109f184d601c1278bcd4eb98d5ee05cc75d7e84f46d072d656502c55544b38c748a1c669468d138e41e5c9d175beffc5 languageName: node linkType: hard @@ -16807,16 +16788,15 @@ __metadata: linkType: hard "expect@npm:^29.6.2": - version: 29.6.2 - resolution: "expect@npm:29.6.2" + version: 29.6.4 + resolution: "expect@npm:29.6.4" dependencies: - "@jest/expect-utils": ^29.6.2 - "@types/node": "*" - jest-get-type: ^29.4.3 - jest-matcher-utils: ^29.6.2 - jest-message-util: ^29.6.2 - jest-util: ^29.6.2 - checksum: c45d700947f23b8d5d034678733a35bdb404c3c1f26163ef692f9a05ae0b85b1918aea030ecf5efb7ffc61f5363593a57247483078187f2406736b5c9e6ceef9 + "@jest/expect-utils": ^29.6.4 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.6.4 + jest-message-util: ^29.6.3 + jest-util: ^29.6.3 + checksum: d3f4ed2fcc33f743b1dd9cf25a07c2f56c9ddd7e1b327d3e74b5febfc90880a9e2ab10c56b3bf31e14d5ead69dc4cb68f718b7fbc3fae8571f8e18675ffe8080 languageName: node linkType: hard @@ -20488,15 +20468,15 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-diff@npm:29.6.2" +"jest-diff@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-diff@npm:29.6.4" dependencies: chalk: ^4.0.0 - diff-sequences: ^29.4.3 - jest-get-type: ^29.4.3 - pretty-format: ^29.6.2 - checksum: 341948de9fbbf9884a93e17a6ff638112109ca640420d62a26753329fdf1d6d0b4582a2a2e894cac4120dc8fb251361d58917288e9f1b955d286b78ab1db29c3 + diff-sequences: ^29.6.3 + jest-get-type: ^29.6.3 + pretty-format: ^29.6.3 + checksum: 5f96be0f15ba8e70acfa5512ca49ba67363678e7ce222889612385a8d9dd042822fdd22a514394fe726b1f462e605bc5d7fc130bd81fa2247e7d40413975d576 languageName: node linkType: hard @@ -20576,7 +20556,7 @@ __metadata: languageName: node linkType: hard -"jest-get-type@npm:^29.4.3, jest-get-type@npm:^29.6.3": +"jest-get-type@npm:^29.6.3": version: 29.6.3 resolution: "jest-get-type@npm:29.6.3" checksum: 552e7a97a983d3c2d4e412a44eb7de0430ff773dd99f7500962c268d6dfbfa431d7d08f919c9d960530e5f7f78eb47f267ad9b318265e5092b3ff9ede0db7c2b @@ -20661,15 +20641,15 @@ __metadata: languageName: node linkType: hard -"jest-matcher-utils@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-matcher-utils@npm:29.6.2" +"jest-matcher-utils@npm:^29.6.4": + version: 29.6.4 + resolution: "jest-matcher-utils@npm:29.6.4" dependencies: chalk: ^4.0.0 - jest-diff: ^29.6.2 - jest-get-type: ^29.4.3 - pretty-format: ^29.6.2 - checksum: 3b383753b8744431a7003c00749ee1ecb16ec4f2e23c8214a95a77e27687d4b3ddd0f4afec85fa5b4ee950c69452de35dc3f07a2da41ff5914dd04bf2decf79e + jest-diff: ^29.6.4 + jest-get-type: ^29.6.3 + pretty-format: ^29.6.3 + checksum: aa54f7075438160bd29e8c0a02d6b7e6ed1f18bab5670d161d1555e5cfa9b61e86306a260ca0304680fb1b357a944fd1d007b6519f91fc6f67d72997b1a7fdb8 languageName: node linkType: hard @@ -20685,20 +20665,20 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-message-util@npm:29.6.2" +"jest-message-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-message-util@npm:29.6.3" dependencies: "@babel/code-frame": ^7.12.13 - "@jest/types": ^29.6.1 + "@jest/types": ^29.6.3 "@types/stack-utils": ^2.0.0 chalk: ^4.0.0 graceful-fs: ^4.2.9 micromatch: ^4.0.4 - pretty-format: ^29.6.2 + pretty-format: ^29.6.3 slash: ^3.0.0 stack-utils: ^2.0.3 - checksum: 4c5624ff281aa9ea09a7fca09f58b39282d3e452651d335d68834795e59c131f20d7fa174ebededa3399f1474af410c434c4dfdba57a99e3e8acf265fbb7c123 + checksum: 5ae17c0aa8076bd0d4c68a036865cf156084cf7b4f69b4ffee0f49da61f7fe9eb38c6405c1f6967df031ffe14f8a31830baa1f04f1dbea52f239689cd4e5b326 languageName: node linkType: hard @@ -20939,17 +20919,17 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.6.2": - version: 29.6.2 - resolution: "jest-util@npm:29.6.2" +"jest-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-util@npm:29.6.3" dependencies: - "@jest/types": ^29.6.1 + "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 ci-info: ^3.2.0 graceful-fs: ^4.2.9 picomatch: ^2.2.3 - checksum: 2510385dc2b828c5de89d1508984ab74edf010377e8a3664549eb1da74f96e8a1badd535b3b8da286c4e2ccfa9de4f07cb501f6c91dc7b5bc5618c248b2b2f0a + checksum: 9428c07696f27aa8f230a13a35546559f9a087f3e3744f53f69a620598234c03004b808b1b4a12120cc5771a88403bf0a1e3f95a7ccd610acf03d90c36135e88 languageName: node linkType: hard @@ -26423,14 +26403,14 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.5.0, pretty-format@npm:^29.6.2": - version: 29.6.2 - resolution: "pretty-format@npm:29.6.2" +"pretty-format@npm:^29.5.0, pretty-format@npm:^29.6.3": + version: 29.6.3 + resolution: "pretty-format@npm:29.6.3" dependencies: - "@jest/schemas": ^29.6.0 + "@jest/schemas": ^29.6.3 ansi-styles: ^5.0.0 react-is: ^18.0.0 - checksum: fb9b404f61c48d1b9408ec93b9dbd0266c1fed36dc99c2ebaa42c1da2354f201a57862a28455ddb573e9b14e74cb8542928c0ef85955b7fd7e3e70ce42e52b32 + checksum: 73c6a46acdad4cb9337add02c850769fb831d7154cdb50b1152f3970a8fbf8292188dcccd1ba597f3e34c360af71fc0b63f1db4cf155a0098ffe2812eb7a6b22 languageName: node linkType: hard From daeffb5e5930ac770e1f06f2fbbff6901e1c8565 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 19 Sep 2023 09:20:15 +0200 Subject: [PATCH 017/524] Move testing library to test package + some improvements --- code/lib/test/package.json | 8 +- code/lib/test/src/expect.ts | 17 ++-- code/lib/test/src/index.ts | 2 + code/lib/test/src/testing-library.ts | 116 +++++++++++++++++++++++++++ code/lib/test/src/utils.ts | 5 ++ code/package.json | 1 - code/yarn.lock | 24 ++---- 7 files changed, 142 insertions(+), 31 deletions(-) create mode 100644 code/lib/test/src/testing-library.ts create mode 100644 code/lib/test/src/utils.ts diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 67cb6a46ea1f..c028e1663218 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -43,12 +43,16 @@ "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { + "@storybook/client-logger": "workspace:^", "@storybook/instrumenter": "workspace:^", - "@testing-library/jest-dom": "^6.0.0", + "@testing-library/dom": "^9.3.1", + "@testing-library/jest-dom": "^6.1.3", + "@testing-library/user-event": "^14.4.3", "@vitest/expect": "^0.34.2", "@vitest/spy": "^0.34.1", "chai": "^4.3.7", - "expect": "^29.6.2" + "expect": "^29.6.2", + "ts-dedent": "^2.2.0" }, "devDependencies": { "@types/chai": "^4", diff --git a/code/lib/test/src/expect.ts b/code/lib/test/src/expect.ts index d9c63b2bbb8d..04d4a05dc366 100644 --- a/code/lib/test/src/expect.ts +++ b/code/lib/test/src/expect.ts @@ -6,7 +6,6 @@ import type { MatchersObject, MatcherState, } from '@vitest/expect'; - import { getState, GLOBAL_EXPECT, @@ -16,21 +15,15 @@ import { setState, } from '@vitest/expect'; import * as matchers from '@testing-library/jest-dom/matchers'; - -type Promisify = { - [K in keyof O]: O[K] extends (...args: infer A) => infer R - ? O extends R - ? Promisify - : (...args: A) => Promise - : O[K]; -}; +import type { PromisifyObject } from './utils'; // We only expose the jest compatible API for now -export interface Assertion extends Promisify> { +export interface Assertion extends PromisifyObject> { toHaveBeenCalledOnce(): Promise; toSatisfy(matcher: (value: E) => boolean, message?: string): Promise; - resolves: Promisify>; - rejects: Promisify>; + resolves: Assertion; + rejects: Assertion; + not: Assertion; } export interface Expect extends AsymmetricMatchersContaining { diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index cd6dc6167a13..2a80a0401e43 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -20,3 +20,5 @@ export const { expect } = instrument( intercept: true, } ); + +export * from './testing-library'; diff --git a/code/lib/test/src/testing-library.ts b/code/lib/test/src/testing-library.ts new file mode 100644 index 000000000000..ade77cdccfc2 --- /dev/null +++ b/code/lib/test/src/testing-library.ts @@ -0,0 +1,116 @@ +/* eslint-disable prefer-destructuring,@typescript-eslint/ban-types */ +import { once } from '@storybook/client-logger'; +import { instrument } from '@storybook/instrumenter'; +import * as domTestingLibrary from '@testing-library/dom'; +import _userEvent from '@testing-library/user-event'; +import dedent from 'ts-dedent'; +import type { FireFunction, FireObject } from '@testing-library/dom/types/events'; +import type { BoundFunctions } from '@testing-library/dom'; +import type { Promisify, PromisifyObject } from './utils'; + +type TestingLibraryDom = typeof domTestingLibrary; + +const testingLibrary = instrument( + { ...domTestingLibrary }, + { + intercept: (method, path) => + path[0] === 'fireEvent' || + method.startsWith('find') || + method.startsWith('waitFor') || + method.startsWith('query') || + method.startsWith('get'), + } +) as {} as PromisifyObject> & { + fireEvent: Promisify & PromisifyObject; + within: ( + element: HTMLElement + ) => PromisifyObject>; +}; + +testingLibrary.screen = new Proxy(testingLibrary.screen, { + get(target, prop, receiver) { + once.warn(dedent` + You are using Testing Library's \`screen\` object. Use \`within(canvasElement)\` instead. + More info: https://storybook.js.org/docs/react/essentials/interactions + `); + return Reflect.get(target, prop, receiver); + }, +}); + +export const { + buildQueries, + configure, + createEvent, + fireEvent, + findAllByAltText, + findAllByDisplayValue, + findAllByLabelText, + findAllByPlaceholderText, + findAllByRole, + findAllByTestId, + findAllByText, + findAllByTitle, + findByAltText, + findByDisplayValue, + findByLabelText, + findByPlaceholderText, + findByRole, + findByTestId, + findByText, + findByTitle, + getAllByAltText, + getAllByDisplayValue, + getAllByLabelText, + getAllByPlaceholderText, + getAllByRole, + getAllByTestId, + getAllByText, + getAllByTitle, + getByAltText, + getByDisplayValue, + getByLabelText, + getByPlaceholderText, + getByRole, + getByTestId, + getByText, + getByTitle, + getConfig, + getDefaultNormalizer, + getElementError, + getNodeText, + getQueriesForElement, + getRoles, + getSuggestedQuery, + isInaccessible, + logDOM, + logRoles, + prettyDOM, + queries, + queryAllByAltText, + queryAllByAttribute, + queryAllByDisplayValue, + queryAllByLabelText, + queryAllByPlaceholderText, + queryAllByRole, + queryAllByTestId, + queryAllByText, + queryAllByTitle, + queryByAltText, + queryByAttribute, + queryByDisplayValue, + queryByLabelText, + queryByPlaceholderText, + queryByRole, + queryByTestId, + queryByText, + queryByTitle, + queryHelpers, + waitFor, + waitForElementToBeRemoved, + within, + prettyFormat, +} = testingLibrary; + +export const screen = testingLibrary.screen; + +export const { userEvent } = instrument({ userEvent: _userEvent }, { intercept: true }); diff --git a/code/lib/test/src/utils.ts b/code/lib/test/src/utils.ts new file mode 100644 index 000000000000..53029f3c5a00 --- /dev/null +++ b/code/lib/test/src/utils.ts @@ -0,0 +1,5 @@ +export type Promisify = Fn extends (...args: infer A) => infer R + ? (...args: A) => R extends Promise ? R : Promise + : Fn; + +export type PromisifyObject = { -readonly [K in keyof O]: Promisify }; diff --git a/code/package.json b/code/package.json index 386254893d93..825d56674a22 100644 --- a/code/package.json +++ b/code/package.json @@ -201,7 +201,6 @@ "@testing-library/dom": "^7.29.4", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.2", - "@testing-library/user-event": "^13.2.1", "@types/express": "^4.17.11", "@types/fs-extra": "^11.0.1", "@types/lodash": "^4.14.167", diff --git a/code/yarn.lock b/code/yarn.lock index 12aec53bd4eb..1f085381e8bf 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6739,7 +6739,7 @@ __metadata: languageName: node linkType: hard -"@storybook/client-logger@workspace:*, @storybook/client-logger@workspace:lib/client-logger": +"@storybook/client-logger@workspace:*, @storybook/client-logger@workspace:^, @storybook/client-logger@workspace:lib/client-logger": version: 0.0.0-use.local resolution: "@storybook/client-logger@workspace:lib/client-logger" dependencies: @@ -7892,7 +7892,6 @@ __metadata: "@testing-library/dom": ^7.29.4 "@testing-library/jest-dom": ^5.11.9 "@testing-library/react": ^11.2.2 - "@testing-library/user-event": ^13.2.1 "@types/express": ^4.17.11 "@types/fs-extra": ^11.0.1 "@types/lodash": ^4.14.167 @@ -8151,13 +8150,17 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/test@workspace:lib/test" dependencies: + "@storybook/client-logger": "workspace:^" "@storybook/instrumenter": "workspace:^" - "@testing-library/jest-dom": ^6.0.0 + "@testing-library/dom": ^9.3.1 + "@testing-library/jest-dom": ^6.1.3 + "@testing-library/user-event": ^14.4.3 "@types/chai": ^4 "@vitest/expect": ^0.34.2 "@vitest/spy": ^0.34.1 chai: ^4.3.7 expect: ^29.6.2 + ts-dedent: ^2.2.0 type-fest: ~2.19 typescript: ~4.9.3 languageName: unknown @@ -8750,7 +8753,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:^9.0.0": +"@testing-library/dom@npm:^9.0.0, @testing-library/dom@npm:^9.3.1": version: 9.3.1 resolution: "@testing-library/dom@npm:9.3.1" dependencies: @@ -8796,18 +8799,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/user-event@npm:^13.2.1": - version: 13.5.0 - resolution: "@testing-library/user-event@npm:13.5.0" - dependencies: - "@babel/runtime": ^7.12.5 - peerDependencies: - "@testing-library/dom": ">=7.21.4" - checksum: ff57edaeab31322c80c3f01d55404b4cebb907b9ec7672b96a1a14d053f172046b01c5f27b45677927ebee8ed91bce695a7d09edec9a48875cfacabe39d0426a - languageName: node - linkType: hard - -"@testing-library/user-event@npm:^14.0.0": +"@testing-library/user-event@npm:^14.0.0, @testing-library/user-event@npm:^14.4.3": version: 14.4.3 resolution: "@testing-library/user-event@npm:14.4.3" peerDependencies: From 1f02904a0999d8a949b8851b8862a2962d342290 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 19 Sep 2023 11:28:24 +0200 Subject: [PATCH 018/524] Add testing library assertion on expect --- code/lib/test/src/expect.ts | 11 ++++++++--- code/package.json | 1 - code/yarn.lock | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/code/lib/test/src/expect.ts b/code/lib/test/src/expect.ts index 04d4a05dc366..d277380a3596 100644 --- a/code/lib/test/src/expect.ts +++ b/code/lib/test/src/expect.ts @@ -15,10 +15,13 @@ import { setState, } from '@vitest/expect'; import * as matchers from '@testing-library/jest-dom/matchers'; +import type { TestingLibraryMatchers } from '@testing-library/jest-dom/types/matchers'; import type { PromisifyObject } from './utils'; // We only expose the jest compatible API for now -export interface Assertion extends PromisifyObject> { +export interface Assertion + extends PromisifyObject>, + TestingLibraryMatchers, Promise> { toHaveBeenCalledOnce(): Promise; toSatisfy(matcher: (value: E) => boolean, message?: string): Promise; resolves: Assertion; @@ -80,7 +83,8 @@ export function createExpect() { expect.getState().assertionCalls }` ); - if (Error.captureStackTrace) Error.captureStackTrace(errorGen(), assertions); + if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') + Error.captureStackTrace(errorGen(), assertions); expect.setState({ expectedAssertionsNumber: expected, @@ -90,7 +94,8 @@ export function createExpect() { function hasAssertions() { const error = new Error('expected any number of assertion, but got none'); - if (Error.captureStackTrace) Error.captureStackTrace(error, hasAssertions); + if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') + Error.captureStackTrace(error, hasAssertions); expect.setState({ isExpectingAssertions: true, diff --git a/code/package.json b/code/package.json index 825d56674a22..910f34d1dace 100644 --- a/code/package.json +++ b/code/package.json @@ -80,7 +80,6 @@ ], "resolutions": { "@playwright/test": "1.36.0", - "@testing-library/jest-dom": "^5.11.9", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/experimental-utils": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", diff --git a/code/yarn.lock b/code/yarn.lock index 1f085381e8bf..582d4f569d5b 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -24,7 +24,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1": +"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.3.0": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: 05672719b544cc0c21ae3ed0eb6349bf458e9d09457578eeeb07cf0f696469ac6417e9c9be1b129e5d6a18098a061c1db55b2275591760ef30a79822436fcbfa @@ -8769,7 +8769,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.11.9": +"@testing-library/jest-dom@npm:^5.11.9, @testing-library/jest-dom@npm:^5.16.2": version: 5.17.0 resolution: "@testing-library/jest-dom@npm:5.17.0" dependencies: @@ -8786,6 +8786,36 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:^6.1.3": + version: 6.1.3 + resolution: "@testing-library/jest-dom@npm:6.1.3" + dependencies: + "@adobe/css-tools": ^4.3.0 + "@babel/runtime": ^7.9.2 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.5.6 + lodash: ^4.17.15 + redent: ^3.0.0 + peerDependencies: + "@jest/globals": ">= 28" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: 544e01939d3c14a3d44ae2e2bb9fe2a0cb5a9e4992ca2728f41188fb9fb2d56e25f1a2e1c12000be2a94d8da36cb220b24020e1b5c5c4c4bede9058a0d80583d + languageName: node + linkType: hard + "@testing-library/react@npm:^11.2.2": version: 11.2.7 resolution: "@testing-library/react@npm:11.2.7" From b406b6df85d3aa689c99f255393c19b343061384 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 20 Sep 2023 14:09:29 +0200 Subject: [PATCH 019/524] Make sure synchronous methods are always promises, even in the first run --- code/lib/instrumenter/src/instrumenter.ts | 6 +++++- code/lib/test/src/index.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 21f05a0ea585..5159050a8a65 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -351,7 +351,11 @@ export class Instrumenter { const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept; const call = { id, cursor, storyId, ancestors, path, method, args, interceptable, retain }; const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke; - const result = interceptOrInvoke.call(this, fn, object, call, options); + const promisifyFn = function (this: unknown, ...args: unknown[]) { + const value = fn.apply(this, args); + return interceptable && typeof value?.then !== 'function' ? Promise.resolve(value) : value; + }; + const result = interceptOrInvoke.call(this, promisifyFn, object, call, options); return this.instrument(result, { ...options, mutate: true, path: [{ __callId__: call.id }] }); } diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 2a80a0401e43..548af7f43d2a 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -17,7 +17,7 @@ export const { expect } = instrument( } return Object.keys(obj); }, - intercept: true, + intercept: (method) => method !== 'expect', } ); From 76c109a4fb652a816348cac313f393cca719b549 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 20 Sep 2023 15:02:35 +0200 Subject: [PATCH 020/524] Revert mistake --- code/package.json | 1 + code/yarn.lock | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/code/package.json b/code/package.json index 910f34d1dace..c1ac7e210b62 100644 --- a/code/package.json +++ b/code/package.json @@ -200,6 +200,7 @@ "@testing-library/dom": "^7.29.4", "@testing-library/jest-dom": "^5.11.9", "@testing-library/react": "^11.2.2", + "@testing-library/user-event": "^13.2.1", "@types/express": "^4.17.11", "@types/fs-extra": "^11.0.1", "@types/lodash": "^4.14.167", diff --git a/code/yarn.lock b/code/yarn.lock index 582d4f569d5b..46dc57b94071 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -7892,6 +7892,7 @@ __metadata: "@testing-library/dom": ^7.29.4 "@testing-library/jest-dom": ^5.11.9 "@testing-library/react": ^11.2.2 + "@testing-library/user-event": ^13.2.1 "@types/express": ^4.17.11 "@types/fs-extra": ^11.0.1 "@types/lodash": ^4.14.167 @@ -8829,6 +8830,17 @@ __metadata: languageName: node linkType: hard +"@testing-library/user-event@npm:^13.2.1": + version: 13.5.0 + resolution: "@testing-library/user-event@npm:13.5.0" + dependencies: + "@babel/runtime": ^7.12.5 + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: ff57edaeab31322c80c3f01d55404b4cebb907b9ec7672b96a1a14d053f172046b01c5f27b45677927ebee8ed91bce695a7d09edec9a48875cfacabe39d0426a + languageName: node + linkType: hard + "@testing-library/user-event@npm:^14.0.0, @testing-library/user-event@npm:^14.4.3": version: 14.4.3 resolution: "@testing-library/user-event@npm:14.4.3" From d034a444559c74b5f3c5838c85ae1956a900ba75 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 20 Sep 2023 15:46:53 +0200 Subject: [PATCH 021/524] Clear spies and instrument spies by event handler name --- code/addons/interactions/src/preview.ts | 21 ++++++++++++++++++++- code/lib/test/src/index.ts | 10 ++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/code/addons/interactions/src/preview.ts b/code/addons/interactions/src/preview.ts index 972126421393..c76e6a3c7a57 100644 --- a/code/addons/interactions/src/preview.ts +++ b/code/addons/interactions/src/preview.ts @@ -12,6 +12,7 @@ import type { } from '@storybook/types'; import { instrument } from '@storybook/instrumenter'; import { ModuleMocker } from 'jest-mock'; +import { Args } from '@storybook/types'; const JestMock = new ModuleMocker(global); const fn = JestMock.fn.bind(JestMock); @@ -56,7 +57,25 @@ const addSpies = (id: string, val: any, key?: string): any => { const addActionsFromArgTypes: ArgsEnhancer = ({ id, initialArgs }) => addSpies(id, initialArgs); -export const argsEnhancers = [addActionsFromArgTypes]; +const instrumentSpies: ArgsEnhancer = ({ initialArgs }) => { + const argTypesWithAction = Object.entries(initialArgs).filter( + ([, value]) => + typeof value === 'function' && + '_isMockFunction' in value && + value._isMockFunction && + !value._instrumented + ); + + return argTypesWithAction.reduce((acc, [key, value]) => { + const instrumented = instrument({ [key]: () => value }, { retain: true })[key]; + acc[key] = instrumented(); + // this enhancer is being called multiple times + value._instrumented = true; + return acc; + }, {} as Args); +}; + +export const argsEnhancers = [addActionsFromArgTypes, instrumentSpies]; export const { step: runStep } = instrument( { diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 548af7f43d2a..7be0af7535f0 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -2,10 +2,16 @@ import { instrument } from '@storybook/instrumenter'; import * as spy from '@vitest/spy'; import chai from 'chai'; import { expect as rawExpect } from './expect'; - +import { FORCE_REMOUNT, STORY_RENDER_PHASE_CHANGED } from '@storybook/core-events'; +import { addons } from '@storybook/preview-api'; export * from '@vitest/spy'; -export const { fn } = instrument({ fn: spy.fn }, { retain: true }); +const channel = addons.getChannel(); + +channel.on(FORCE_REMOUNT, () => spy.spies.forEach((mock) => mock.mockClear())); +channel.on(STORY_RENDER_PHASE_CHANGED, ({ newPhase }) => { + if (newPhase === 'loading') spy.spies.forEach((mock) => mock.mockClear()); +}); export const { expect } = instrument( { expect: rawExpect }, From e6b0f0a19e341f5f3a79dbccd15736736efbd9bc Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 20 Sep 2023 16:56:25 +0200 Subject: [PATCH 022/524] Show deprecation message --- code/addons/actions/src/addArgsHelpers.ts | 2 +- .../actions/src/models/ActionOptions.ts | 1 + code/addons/actions/src/runtime/action.ts | 20 +++++++++++++++++++ code/addons/interactions/src/preview.ts | 5 +++-- code/lib/instrumenter/src/instrumenter.ts | 5 +++-- code/lib/test/package.json | 2 ++ code/lib/test/src/index.ts | 3 ++- 7 files changed, 32 insertions(+), 6 deletions(-) diff --git a/code/addons/actions/src/addArgsHelpers.ts b/code/addons/actions/src/addArgsHelpers.ts index fd93bea6e6f0..0dcb56c32f55 100644 --- a/code/addons/actions/src/addArgsHelpers.ts +++ b/code/addons/actions/src/addArgsHelpers.ts @@ -32,7 +32,7 @@ export const inferActionsFromArgTypesRegex: ArgsEnhancer = (context) = return argTypesMatchingRegex.reduce((acc, [name, argType]) => { if (isInInitialArgs(name, initialArgs)) { - acc[name] = action(name); + acc[name] = action(name, { implicit: true }); } return acc; }, {} as Args); diff --git a/code/addons/actions/src/models/ActionOptions.ts b/code/addons/actions/src/models/ActionOptions.ts index 6678e5138929..b503df069d5c 100644 --- a/code/addons/actions/src/models/ActionOptions.ts +++ b/code/addons/actions/src/models/ActionOptions.ts @@ -4,6 +4,7 @@ interface Options { depth: number; // backards compatibility, remove in 7.0 clearOnStoryChange: boolean; limit: number; + implicit: boolean; } export type ActionOptions = Partial & Partial; diff --git a/code/addons/actions/src/runtime/action.ts b/code/addons/actions/src/runtime/action.ts index b17647949b86..889e39405848 100644 --- a/code/addons/actions/src/runtime/action.ts +++ b/code/addons/actions/src/runtime/action.ts @@ -1,5 +1,9 @@ +/* eslint-disable no-underscore-dangle */ import { v4 as uuidv4 } from 'uuid'; +import type { PreviewWeb } from '@storybook/preview-api'; import { addons } from '@storybook/preview-api'; +import type { Renderer } from '@storybook/types'; +import { global } from '@storybook/global'; import { EVENT_ID } from '../constants'; import type { ActionDisplay, ActionOptions, HandlerFunction } from '../models'; import { config } from './configureActions'; @@ -46,6 +50,22 @@ export function action(name: string, options: ActionOptions = {}): HandlerFuncti }; const handler = function actionHandler(...args: any[]) { + if (options.implicit) { + const preview = + '__STORYBOOK_PREVIEW__' in global + ? (global.__STORYBOOK_PREVIEW__ as PreviewWeb) + : undefined; + if ( + preview?.storyRenders.some( + (render) => render.phase === 'playing' || render.phase === 'rendering' + ) + ) { + console.warn( + 'Can not use implicit actions during rendering or playing of a story. \nSee: [docs page]' + ); + } + } + const channel = addons.getChannel(); const id = uuidv4(); const minDepth = 5; // anything less is really just storybook internals diff --git a/code/addons/interactions/src/preview.ts b/code/addons/interactions/src/preview.ts index c76e6a3c7a57..d393a0aefb20 100644 --- a/code/addons/interactions/src/preview.ts +++ b/code/addons/interactions/src/preview.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-param-reassign,no-underscore-dangle */ /// import { addons } from '@storybook/preview-api'; @@ -9,10 +10,10 @@ import type { PlayFunction, PlayFunctionContext, StepLabel, + Args, } from '@storybook/types'; import { instrument } from '@storybook/instrumenter'; import { ModuleMocker } from 'jest-mock'; -import { Args } from '@storybook/types'; const JestMock = new ModuleMocker(global); const fn = JestMock.fn.bind(JestMock); @@ -34,7 +35,7 @@ const addSpies = (id: string, val: any, key?: string): any => { try { if (Object.prototype.toString.call(val) === '[object Object]') { // We have to mutate the original object for this to survive HMR. - // eslint-disable-next-line no-restricted-syntax, no-param-reassign + // eslint-disable-next-line no-restricted-syntax for (const [k, v] of Object.entries(val)) val[k] = addSpies(id, v, k); return val; } diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 5159050a8a65..9402baf56117 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -351,8 +351,9 @@ export class Instrumenter { const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept; const call = { id, cursor, storyId, ancestors, path, method, args, interceptable, retain }; const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke; - const promisifyFn = function (this: unknown, ...args: unknown[]) { - const value = fn.apply(this, args); + // eslint-disable-next-line func-names + const promisifyFn = function (this: unknown, ...argz: unknown[]) { + const value = fn.apply(this, argz); return interceptable && typeof value?.then !== 'function' ? Promise.resolve(value) : value; }; const result = interceptOrInvoke.call(this, promisifyFn, object, call, options); diff --git a/code/lib/test/package.json b/code/lib/test/package.json index c028e1663218..38deca4b37bd 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -44,6 +44,8 @@ }, "dependencies": { "@storybook/client-logger": "workspace:^", + "@storybook/core-events": "workspace:^", + "@storybook/preview-api": "workspace:^", "@storybook/instrumenter": "workspace:^", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.1.3", diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 7be0af7535f0..cc3cbdf85367 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -1,9 +1,10 @@ import { instrument } from '@storybook/instrumenter'; import * as spy from '@vitest/spy'; import chai from 'chai'; -import { expect as rawExpect } from './expect'; import { FORCE_REMOUNT, STORY_RENDER_PHASE_CHANGED } from '@storybook/core-events'; import { addons } from '@storybook/preview-api'; +import { expect as rawExpect } from './expect'; + export * from '@vitest/spy'; const channel = addons.getChannel(); From 9d880277a8cd23740d0e77443e3b5ebdb9b8e9a3 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 21 Sep 2023 16:49:59 +0200 Subject: [PATCH 023/524] Revert making get* method's promises and make sure we instrument `not` --- code/lib/instrumenter/src/instrumenter.ts | 44 +++++++++++++++++------ code/lib/instrumenter/src/types.ts | 2 +- code/lib/test/src/index.ts | 7 ++-- code/lib/test/src/testing-library.ts | 15 ++------ 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 9402baf56117..93fce9c957cd 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -1,4 +1,4 @@ -/* eslint-disable no-underscore-dangle */ +/* eslint-disable no-underscore-dangle,no-param-reassign */ import type { Channel } from '@storybook/channels'; import { addons } from '@storybook/preview-api'; import type { StoryId } from '@storybook/types'; @@ -289,19 +289,34 @@ export class Instrumenter { // Traverses the object structure to recursively patch all function properties. // Returns the original object, or a new object with the same constructor, // depending on whether it should mutate. - instrument>(obj: TObj, options: Options): PatchedObj { + instrument>( + obj: TObj, + options: Options, + depth = 0 + ): PatchedObj { if (!isInstrumentable(obj)) return obj as PatchedObj; const { mutate = false, path = [] } = options; - const keys = options.getKeys ? options.getKeys(obj) : Object.keys(obj); + const keys = options.getKeys ? options.getKeys(obj, depth) : Object.keys(obj); + depth += 1; return keys.reduce( (acc, key) => { const value = (obj as Record)[key]; // Nothing to patch, but might be instrumentable, so we recurse if (typeof value !== 'function') { - acc[key] = this.instrument(value, { ...options, path: path.concat(key) }); + const instrumented = this.instrument( + value, + { ...options, path: path.concat(key) }, + depth + ); + const descriptor = getPropertyDescriptor(obj, key); + if (typeof descriptor?.get === 'function') { + Object.defineProperty(acc, key, { get: () => instrumented }); + } else { + acc[key] = instrumented; + } return acc; } @@ -322,7 +337,7 @@ export class Instrumenter { if (Object.keys(value).length > 0) { Object.assign( acc[key], - this.instrument({ ...value }, { ...options, path: path.concat(key) }) + this.instrument({ ...value }, { ...options, path: path.concat(key) }, depth) ); } @@ -351,12 +366,7 @@ export class Instrumenter { const interceptable = typeof intercept === 'function' ? intercept(method, path) : intercept; const call = { id, cursor, storyId, ancestors, path, method, args, interceptable, retain }; const interceptOrInvoke = interceptable && !ancestors.length ? this.intercept : this.invoke; - // eslint-disable-next-line func-names - const promisifyFn = function (this: unknown, ...argz: unknown[]) { - const value = fn.apply(this, argz); - return interceptable && typeof value?.then !== 'function' ? Promise.resolve(value) : value; - }; - const result = interceptOrInvoke.call(this, promisifyFn, object, call, options); + const result = interceptOrInvoke.call(this, fn, object, call, options); return this.instrument(result, { ...options, mutate: true, path: [{ __callId__: call.id }] }); } @@ -649,3 +659,15 @@ export function instrument>( return obj; } } + +function getPropertyDescriptor(obj: T, propName: keyof T) { + let target = obj; + while (target != null) { + const descriptor = Object.getOwnPropertyDescriptor(target, propName); + if (descriptor) { + return descriptor; + } + target = Object.getPrototypeOf(target); + } + return undefined; +} diff --git a/code/lib/instrumenter/src/types.ts b/code/lib/instrumenter/src/types.ts index bfcfc42d1b45..0a528a5c161a 100644 --- a/code/lib/instrumenter/src/types.ts +++ b/code/lib/instrumenter/src/types.ts @@ -90,5 +90,5 @@ export interface Options { mutate?: boolean; path?: Array; getArgs?: (call: Call, state: State) => Call['args']; - getKeys?: (originalObject: Record) => string[]; + getKeys?: (originalObject: Record, depth: number) => string[]; } diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index cc3cbdf85367..7b832fb052e9 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -17,10 +17,13 @@ channel.on(STORY_RENDER_PHASE_CHANGED, ({ newPhase }) => { export const { expect } = instrument( { expect: rawExpect }, { - getKeys: (obj: Record) => { + getKeys: (obj: Record, depth) => { const privateApi = ['assert', '__methods', '__flags']; if (obj.constructor === chai.Assertion) { - return Object.keys(Object.getPrototypeOf(obj)).filter((it) => !privateApi.includes(it)); + const keys = Object.keys(Object.getPrototypeOf(obj)).filter( + (it) => !privateApi.includes(it) + ); + return depth > 2 ? keys : [...keys, 'not']; } return Object.keys(obj); }, diff --git a/code/lib/test/src/testing-library.ts b/code/lib/test/src/testing-library.ts index ade77cdccfc2..f438a9b6e5bf 100644 --- a/code/lib/test/src/testing-library.ts +++ b/code/lib/test/src/testing-library.ts @@ -5,7 +5,6 @@ import * as domTestingLibrary from '@testing-library/dom'; import _userEvent from '@testing-library/user-event'; import dedent from 'ts-dedent'; import type { FireFunction, FireObject } from '@testing-library/dom/types/events'; -import type { BoundFunctions } from '@testing-library/dom'; import type { Promisify, PromisifyObject } from './utils'; type TestingLibraryDom = typeof domTestingLibrary; @@ -14,17 +13,10 @@ const testingLibrary = instrument( { ...domTestingLibrary }, { intercept: (method, path) => - path[0] === 'fireEvent' || - method.startsWith('find') || - method.startsWith('waitFor') || - method.startsWith('query') || - method.startsWith('get'), + path[0] === 'fireEvent' || method.startsWith('find') || method.startsWith('waitFor'), } -) as {} as PromisifyObject> & { +) as {} as PromisifyObject> & { fireEvent: Promisify & PromisifyObject; - within: ( - element: HTMLElement - ) => PromisifyObject>; }; testingLibrary.screen = new Proxy(testingLibrary.screen, { @@ -105,12 +97,11 @@ export const { queryByText, queryByTitle, queryHelpers, + screen, waitFor, waitForElementToBeRemoved, within, prettyFormat, } = testingLibrary; -export const screen = testingLibrary.screen; - export const { userEvent } = instrument({ userEvent: _userEvent }, { intercept: true }); From ea2c3c36d9c22d4c90d46434631088ff154f6831 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 21 Sep 2023 14:57:17 +0200 Subject: [PATCH 024/524] fix yarn lock --- code/lib/test/package.json | 2 +- code/yarn.lock | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 38deca4b37bd..f5b45934111d 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -45,8 +45,8 @@ "dependencies": { "@storybook/client-logger": "workspace:^", "@storybook/core-events": "workspace:^", - "@storybook/preview-api": "workspace:^", "@storybook/instrumenter": "workspace:^", + "@storybook/preview-api": "workspace:^", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.1.3", "@testing-library/user-event": "^14.4.3", diff --git a/code/yarn.lock b/code/yarn.lock index 46dc57b94071..9e190072ad23 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6865,7 +6865,7 @@ __metadata: languageName: unknown linkType: soft -"@storybook/core-events@workspace:*, @storybook/core-events@workspace:lib/core-events": +"@storybook/core-events@workspace:*, @storybook/core-events@workspace:^, @storybook/core-events@workspace:lib/core-events": version: 0.0.0-use.local resolution: "@storybook/core-events@workspace:lib/core-events" dependencies: @@ -7616,7 +7616,7 @@ __metadata: languageName: unknown linkType: soft -"@storybook/preview-api@workspace:*, @storybook/preview-api@workspace:lib/preview-api": +"@storybook/preview-api@workspace:*, @storybook/preview-api@workspace:^, @storybook/preview-api@workspace:lib/preview-api": version: 0.0.0-use.local resolution: "@storybook/preview-api@workspace:lib/preview-api" dependencies: @@ -8152,7 +8152,9 @@ __metadata: resolution: "@storybook/test@workspace:lib/test" dependencies: "@storybook/client-logger": "workspace:^" + "@storybook/core-events": "workspace:^" "@storybook/instrumenter": "workspace:^" + "@storybook/preview-api": "workspace:^" "@testing-library/dom": ^9.3.1 "@testing-library/jest-dom": ^6.1.3 "@testing-library/user-event": ^14.4.3 From 33cbcae5d6ddc37b6ad60f26d44ca4a4230b47e4 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 21 Sep 2023 17:14:38 +0200 Subject: [PATCH 025/524] Fix eslint --- code/lib/test/src/testing-library.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lib/test/src/testing-library.ts b/code/lib/test/src/testing-library.ts index f438a9b6e5bf..eb65fb1dcccf 100644 --- a/code/lib/test/src/testing-library.ts +++ b/code/lib/test/src/testing-library.ts @@ -1,4 +1,4 @@ -/* eslint-disable prefer-destructuring,@typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/ban-types */ import { once } from '@storybook/client-logger'; import { instrument } from '@storybook/instrumenter'; import * as domTestingLibrary from '@testing-library/dom'; From 6d1986118f3814727f68dc8f02b5d8d17dc3ff2c Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 09:20:49 +0200 Subject: [PATCH 026/524] Comment out deprecation for now --- code/addons/actions/src/runtime/action.ts | 35 +++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/code/addons/actions/src/runtime/action.ts b/code/addons/actions/src/runtime/action.ts index 889e39405848..a0f6b1b08554 100644 --- a/code/addons/actions/src/runtime/action.ts +++ b/code/addons/actions/src/runtime/action.ts @@ -1,9 +1,5 @@ -/* eslint-disable no-underscore-dangle */ import { v4 as uuidv4 } from 'uuid'; -import type { PreviewWeb } from '@storybook/preview-api'; import { addons } from '@storybook/preview-api'; -import type { Renderer } from '@storybook/types'; -import { global } from '@storybook/global'; import { EVENT_ID } from '../constants'; import type { ActionDisplay, ActionOptions, HandlerFunction } from '../models'; import { config } from './configureActions'; @@ -50,21 +46,22 @@ export function action(name: string, options: ActionOptions = {}): HandlerFuncti }; const handler = function actionHandler(...args: any[]) { - if (options.implicit) { - const preview = - '__STORYBOOK_PREVIEW__' in global - ? (global.__STORYBOOK_PREVIEW__ as PreviewWeb) - : undefined; - if ( - preview?.storyRenders.some( - (render) => render.phase === 'playing' || render.phase === 'rendering' - ) - ) { - console.warn( - 'Can not use implicit actions during rendering or playing of a story. \nSee: [docs page]' - ); - } - } + // TODO: Enable once codemods are finished + // if (options.implicit) { + // const preview = + // '__STORYBOOK_PREVIEW__' in global + // ? (global.__STORYBOOK_PREVIEW__ as PreviewWeb) + // : undefined; + // if ( + // preview?.storyRenders.some( + // (render) => render.phase === 'playing' || render.phase === 'rendering' + // ) + // ) { + // console.warn( + // 'Can not use implicit actions during rendering or playing of a story.' + // ); + // } + // } const channel = addons.getChannel(); const id = uuidv4(); From 0b7671618d7afc4b8d9dcb0d65292409273951c9 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 09:37:33 +0200 Subject: [PATCH 027/524] Fix types --- code/lib/test/package.json | 2 +- code/lib/test/src/testing-library.ts | 3 ++- code/lib/test/src/utils.ts | 2 +- code/yarn.lock | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index f5b45934111d..079153c58365 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "@types/chai": "^4", - "type-fest": "~2.19", + "type-fest": "^2.19.0", "typescript": "~4.9.3" }, "publishConfig": { diff --git a/code/lib/test/src/testing-library.ts b/code/lib/test/src/testing-library.ts index eb65fb1dcccf..ccac1f448923 100644 --- a/code/lib/test/src/testing-library.ts +++ b/code/lib/test/src/testing-library.ts @@ -5,6 +5,7 @@ import * as domTestingLibrary from '@testing-library/dom'; import _userEvent from '@testing-library/user-event'; import dedent from 'ts-dedent'; import type { FireFunction, FireObject } from '@testing-library/dom/types/events'; +import type { Writable } from 'type-fest'; import type { Promisify, PromisifyObject } from './utils'; type TestingLibraryDom = typeof domTestingLibrary; @@ -15,7 +16,7 @@ const testingLibrary = instrument( intercept: (method, path) => path[0] === 'fireEvent' || method.startsWith('find') || method.startsWith('waitFor'), } -) as {} as PromisifyObject> & { +) as {} as Writable> & { fireEvent: Promisify & PromisifyObject; }; diff --git a/code/lib/test/src/utils.ts b/code/lib/test/src/utils.ts index 53029f3c5a00..6f093cd0b9f4 100644 --- a/code/lib/test/src/utils.ts +++ b/code/lib/test/src/utils.ts @@ -2,4 +2,4 @@ export type Promisify = Fn extends (...args: infer A) => infer R ? (...args: A) => R extends Promise ? R : Promise : Fn; -export type PromisifyObject = { -readonly [K in keyof O]: Promisify }; +export type PromisifyObject = { [K in keyof O]: Promisify }; diff --git a/code/yarn.lock b/code/yarn.lock index 9e190072ad23..19d39aa333bf 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8164,7 +8164,7 @@ __metadata: chai: ^4.3.7 expect: ^29.6.2 ts-dedent: ^2.2.0 - type-fest: ~2.19 + type-fest: ^4.3.1 typescript: ~4.9.3 languageName: unknown linkType: soft From da91e3dd85916f97d5b3403069d78c62edca5948 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 12:00:50 +0200 Subject: [PATCH 028/524] Make getters lazy and fix workspace --- code/lib/instrumenter/src/instrumenter.ts | 14 ++++++-------- code/lib/test/package.json | 8 ++++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 93fce9c957cd..c9ed517e054a 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -303,19 +303,17 @@ export class Instrumenter { return keys.reduce( (acc, key) => { const value = (obj as Record)[key]; - // Nothing to patch, but might be instrumentable, so we recurse if (typeof value !== 'function') { - const instrumented = this.instrument( - value, - { ...options, path: path.concat(key) }, - depth - ); const descriptor = getPropertyDescriptor(obj, key); if (typeof descriptor?.get === 'function') { - Object.defineProperty(acc, key, { get: () => instrumented }); + Object.defineProperty(acc, key, { + get: () => { + return this.instrument(value, { ...options, path: path.concat(key) }, depth); + }, + }); } else { - acc[key] = instrumented; + acc[key] = this.instrument(value, { ...options, path: path.concat(key) }, depth); } return acc; } diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 079153c58365..167506f544da 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -43,10 +43,10 @@ "prep": "../../../scripts/prepare/bundle.ts" }, "dependencies": { - "@storybook/client-logger": "workspace:^", - "@storybook/core-events": "workspace:^", - "@storybook/instrumenter": "workspace:^", - "@storybook/preview-api": "workspace:^", + "@storybook/client-logger": "workspace:*", + "@storybook/core-events": "workspace:*", + "@storybook/instrumenter": "workspace:*", + "@storybook/preview-api": "workspace:*", "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.1.3", "@testing-library/user-event": "^14.4.3", From 17b3a3312c68a0caae044c6c274fb97de682c07c Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 12:04:05 +0200 Subject: [PATCH 029/524] Fix yarn.lock --- code/yarn.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/code/yarn.lock b/code/yarn.lock index 19d39aa333bf..11eb4211c578 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6739,7 +6739,7 @@ __metadata: languageName: node linkType: hard -"@storybook/client-logger@workspace:*, @storybook/client-logger@workspace:^, @storybook/client-logger@workspace:lib/client-logger": +"@storybook/client-logger@workspace:*, @storybook/client-logger@workspace:lib/client-logger": version: 0.0.0-use.local resolution: "@storybook/client-logger@workspace:lib/client-logger" dependencies: @@ -6865,7 +6865,7 @@ __metadata: languageName: unknown linkType: soft -"@storybook/core-events@workspace:*, @storybook/core-events@workspace:^, @storybook/core-events@workspace:lib/core-events": +"@storybook/core-events@workspace:*, @storybook/core-events@workspace:lib/core-events": version: 0.0.0-use.local resolution: "@storybook/core-events@workspace:lib/core-events" dependencies: @@ -7157,7 +7157,7 @@ __metadata: languageName: node linkType: hard -"@storybook/instrumenter@workspace:*, @storybook/instrumenter@workspace:^, @storybook/instrumenter@workspace:lib/instrumenter": +"@storybook/instrumenter@workspace:*, @storybook/instrumenter@workspace:lib/instrumenter": version: 0.0.0-use.local resolution: "@storybook/instrumenter@workspace:lib/instrumenter" dependencies: @@ -7616,7 +7616,7 @@ __metadata: languageName: unknown linkType: soft -"@storybook/preview-api@workspace:*, @storybook/preview-api@workspace:^, @storybook/preview-api@workspace:lib/preview-api": +"@storybook/preview-api@workspace:*, @storybook/preview-api@workspace:lib/preview-api": version: 0.0.0-use.local resolution: "@storybook/preview-api@workspace:lib/preview-api" dependencies: @@ -8151,10 +8151,10 @@ __metadata: version: 0.0.0-use.local resolution: "@storybook/test@workspace:lib/test" dependencies: - "@storybook/client-logger": "workspace:^" - "@storybook/core-events": "workspace:^" - "@storybook/instrumenter": "workspace:^" - "@storybook/preview-api": "workspace:^" + "@storybook/client-logger": "workspace:*" + "@storybook/core-events": "workspace:*" + "@storybook/instrumenter": "workspace:*" + "@storybook/preview-api": "workspace:*" "@testing-library/dom": ^9.3.1 "@testing-library/jest-dom": ^6.1.3 "@testing-library/user-event": ^14.4.3 @@ -8164,7 +8164,7 @@ __metadata: chai: ^4.3.7 expect: ^29.6.2 ts-dedent: ^2.2.0 - type-fest: ^4.3.1 + type-fest: ^2.19.0 typescript: ~4.9.3 languageName: unknown linkType: soft From fae8299dd244ab2763ffa03fc9c73ac78232d0f9 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 12:26:39 +0200 Subject: [PATCH 030/524] Fix type fest range --- code/lib/test/package.json | 2 +- code/yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 167506f544da..b19dc90932a9 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -58,7 +58,7 @@ }, "devDependencies": { "@types/chai": "^4", - "type-fest": "^2.19.0", + "type-fest": "~2.19", "typescript": "~4.9.3" }, "publishConfig": { diff --git a/code/yarn.lock b/code/yarn.lock index 11eb4211c578..5096467d8d1f 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8164,7 +8164,7 @@ __metadata: chai: ^4.3.7 expect: ^29.6.2 ts-dedent: ^2.2.0 - type-fest: ^2.19.0 + type-fest: ~2.19 typescript: ~4.9.3 languageName: unknown linkType: soft From 2085dd4394eacb0b77d602d9792e315bfaad2851 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 16:45:54 +0200 Subject: [PATCH 031/524] Patch vitest to make it compatible with the jest runner --- .../@vitest-expect-npm-0.34.3-313878cdb4.patch | 15 +++++++++++++++ code/jest.config.base.js | 1 + code/lib/test/package.json | 8 +++++--- code/package.json | 3 ++- code/yarn.lock | 15 ++++++++++++++- scripts/package.json | 1 + 6 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch diff --git a/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch b/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch new file mode 100644 index 000000000000..c9320c82c04c --- /dev/null +++ b/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch @@ -0,0 +1,15 @@ +diff --git a/dist/index.js b/dist/index.js +index 9fd849550098f37f44ac6f9f64ad174cc821759a..44afa9ccbc42dd81e07ffa794b4be89c61d00c37 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -6,7 +6,9 @@ import { isMockFunction } from '@vitest/spy'; + import { processError } from '@vitest/utils/error'; + + const MATCHERS_OBJECT = Symbol.for("matchers-object"); +-const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object"); ++// Patched this symbol for storybook, so that @storybook/test can be used in a jest environment as well. ++// Otherwise, vitest will override global jest matchers, and crash. ++const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object-storybook"); + const GLOBAL_EXPECT = Symbol.for("expect-global"); + + if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) { diff --git a/code/jest.config.base.js b/code/jest.config.base.js index 9fdc75f588a9..59cb8cf3c37e 100644 --- a/code/jest.config.base.js +++ b/code/jest.config.base.js @@ -23,6 +23,7 @@ const modulesToTransform = [ '@angular', '@lit', '@mdx-js', + '@vitest', 'ccount', 'character-entities', 'decode-named-character-reference', diff --git a/code/lib/test/package.json b/code/lib/test/package.json index b19dc90932a9..728bb3674f35 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -50,16 +50,18 @@ "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.1.3", "@testing-library/user-event": "^14.4.3", - "@vitest/expect": "^0.34.2", - "@vitest/spy": "^0.34.1", "chai": "^4.3.7", "expect": "^29.6.2", + "loupe": "^2.3.1", "ts-dedent": "^2.2.0" }, "devDependencies": { "@types/chai": "^4", + "@vitest/expect": "^0.34.2", + "@vitest/spy": "^0.34.1", "type-fest": "~2.19", - "typescript": "~4.9.3" + "typescript": "~4.9.3", + "util": "^0.12.4" }, "publishConfig": { "access": "public" diff --git a/code/package.json b/code/package.json index c1ac7e210b62..cea806bec2a4 100644 --- a/code/package.json +++ b/code/package.json @@ -88,7 +88,8 @@ "playwright": "1.36.0", "playwright-core": "1.36.0", "serialize-javascript": "^3.1.0", - "type-fest": "~2.19" + "type-fest": "~2.19", + "@vitest/expect@^0.34.2": "patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch" }, "dependencies": { "@babel/core": "^7.22.9", diff --git a/code/yarn.lock b/code/yarn.lock index 5096467d8d1f..e23a148e965d 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8163,9 +8163,11 @@ __metadata: "@vitest/spy": ^0.34.1 chai: ^4.3.7 expect: ^29.6.2 + loupe: ^2.3.1 ts-dedent: ^2.2.0 type-fest: ~2.19 typescript: ~4.9.3 + util: ^0.12.4 languageName: unknown linkType: soft @@ -10205,7 +10207,7 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:^0.34.2": +"@vitest/expect@npm:0.34.3": version: 0.34.3 resolution: "@vitest/expect@npm:0.34.3" dependencies: @@ -10216,6 +10218,17 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch::locator=%40storybook%2Froot%40workspace%3A.": + version: 0.34.3 + resolution: "@vitest/expect@patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch::version=0.34.3&hash=2c0ce2&locator=%40storybook%2Froot%40workspace%3A." + dependencies: + "@vitest/spy": 0.34.3 + "@vitest/utils": 0.34.3 + chai: ^4.3.7 + checksum: 6800fea8b719928002ba7b87f92e07f67ab9f21da38fb8e4e1ef6e27ea6e37f3418ea72f2d828706558e921ae8f63c6460b97cdc1ed276b8b7c6ff66889001d7 + languageName: node + linkType: hard + "@vitest/spy@npm:0.34.3, @vitest/spy@npm:^0.34.1": version: 0.34.3 resolution: "@vitest/spy@npm:0.34.3" diff --git a/scripts/package.json b/scripts/package.json index 906bb2b95926..e9a7bb490fc4 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -89,6 +89,7 @@ "@types/express": "^4.17.11", "@types/fs-extra": "^11.0.1", "@types/http-server": "^0.12.1", + "@types/jest": "^29.5.5", "@types/lodash": "^4", "@types/node": "^16.0.0", "@types/node-fetch": "^2.5.7", From 39ed28da9ee4a99fb4cdfaddd226826d494d3216 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 16:55:58 +0200 Subject: [PATCH 032/524] Add jest types to lock --- scripts/yarn.lock | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/yarn.lock b/scripts/yarn.lock index ee273eaf2d45..1fd9dc94ad92 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -2922,6 +2922,7 @@ __metadata: "@types/express": ^4.17.11 "@types/fs-extra": ^11.0.1 "@types/http-server": ^0.12.1 + "@types/jest": ^29.5.5 "@types/lodash": ^4 "@types/node": ^16.0.0 "@types/node-fetch": ^2.5.7 @@ -3567,6 +3568,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^29.5.5": + version: 29.5.5 + resolution: "@types/jest@npm:29.5.5" + dependencies: + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: 0a3481f119099e6a0a381fec0d410cd33241267a0981576a7a832687fc3f888f79285289dc7c054c3589fd443f7ed1598d25fa7bc9708491b58da17e423b4aff + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.1 resolution: "@types/jsdom@npm:20.0.1" From ddd8bf1e1c553af80cc258db12db094f748eab33 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 20:42:39 +0200 Subject: [PATCH 033/524] Better patch --- ...@vitest-expect-npm-0.34.3-313878cdb4.patch | 15 -------- code/package.json | 2 +- code/yarn.lock | 34 +++++++++---------- 3 files changed, 17 insertions(+), 34 deletions(-) delete mode 100644 code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch diff --git a/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch b/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch deleted file mode 100644 index c9320c82c04c..000000000000 --- a/code/.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/dist/index.js b/dist/index.js -index 9fd849550098f37f44ac6f9f64ad174cc821759a..44afa9ccbc42dd81e07ffa794b4be89c61d00c37 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -6,7 +6,9 @@ import { isMockFunction } from '@vitest/spy'; - import { processError } from '@vitest/utils/error'; - - const MATCHERS_OBJECT = Symbol.for("matchers-object"); --const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object"); -+// Patched this symbol for storybook, so that @storybook/test can be used in a jest environment as well. -+// Otherwise, vitest will override global jest matchers, and crash. -+const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object-storybook"); - const GLOBAL_EXPECT = Symbol.for("expect-global"); - - if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) { diff --git a/code/package.json b/code/package.json index cea806bec2a4..e04af9bd2da7 100644 --- a/code/package.json +++ b/code/package.json @@ -89,7 +89,7 @@ "playwright-core": "1.36.0", "serialize-javascript": "^3.1.0", "type-fest": "~2.19", - "@vitest/expect@^0.34.2": "patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch" + "@vitest/expect@^0.34.2": "patch:@vitest/expect@npm%3A0.34.5#./.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch" }, "dependencies": { "@babel/core": "^7.22.9", diff --git a/code/yarn.lock b/code/yarn.lock index e23a148e965d..889b85d0ed19 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -10207,29 +10207,27 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/expect@npm:0.34.3" +"@vitest/expect@npm:^0.34.2": + version: 0.34.5 + resolution: "@vitest/expect@npm:0.34.5" dependencies: - "@vitest/spy": 0.34.3 - "@vitest/utils": 0.34.3 + "@vitest/spy": 0.34.5 + "@vitest/utils": 0.34.5 chai: ^4.3.7 - checksum: ec70fba265b5bbd31f9c06c60e504ee0f1394df0871a5bddbe0a6b0a2436705f5e41e183fcdec3dd8864b5432b14d4f3802b896ba625ae0a44b52a9a08ddbd73 + checksum: dc30a5e1f2732a1906df57f65381df1129dbf994496734c27e4a3f832852862501eaba1ec2987215ec12ee23a8f2ef1d8ff63c7cd5490046a7a26800da1adcb2 languageName: node linkType: hard -"@vitest/expect@patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch::locator=%40storybook%2Froot%40workspace%3A.": - version: 0.34.3 - resolution: "@vitest/expect@patch:@vitest/expect@npm%3A0.34.3#./.yarn/patches/@vitest-expect-npm-0.34.3-313878cdb4.patch::version=0.34.3&hash=2c0ce2&locator=%40storybook%2Froot%40workspace%3A." +"@vitest/spy@npm:0.34.5": + version: 0.34.5 + resolution: "@vitest/spy@npm:0.34.5" dependencies: - "@vitest/spy": 0.34.3 - "@vitest/utils": 0.34.3 - chai: ^4.3.7 - checksum: 6800fea8b719928002ba7b87f92e07f67ab9f21da38fb8e4e1ef6e27ea6e37f3418ea72f2d828706558e921ae8f63c6460b97cdc1ed276b8b7c6ff66889001d7 + tinyspy: ^2.1.1 + checksum: bbee495ca6300f50dde6418d14db0d3281daf38df15abae95202ddef253d6dd8bedf9f4a79da5a2246d3758ab24aa737caccf752fabcd8ba902a4f14801c2a0c languageName: node linkType: hard -"@vitest/spy@npm:0.34.3, @vitest/spy@npm:^0.34.1": +"@vitest/spy@npm:^0.34.1": version: 0.34.3 resolution: "@vitest/spy@npm:0.34.3" dependencies: @@ -10238,14 +10236,14 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:0.34.3": - version: 0.34.3 - resolution: "@vitest/utils@npm:0.34.3" +"@vitest/utils@npm:0.34.5": + version: 0.34.5 + resolution: "@vitest/utils@npm:0.34.5" dependencies: diff-sequences: ^29.4.3 loupe: ^2.3.6 pretty-format: ^29.5.0 - checksum: 7ca2d82c4286b963b8d8004812464c81b42d73d027b739fa5b2f2cdfb2a14e409f8ad1da6c269ba7379c74a93bb0e81485b2040a18a06a886b49c4bef1e494ab + checksum: 99cc5974ada1dab2b02220005c0fc97147baba175601a0faa1b2b6687c7f579d21a401077377d6f759b3aa8a07dcc8851cdc3e07f9a550ec289286107487ac36 languageName: node linkType: hard From 27ded25db5df02be7f920e1697a6d255c8ac054e Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Fri, 22 Sep 2023 20:49:47 +0200 Subject: [PATCH 034/524] Fix lock --- code/yarn.lock | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/code/yarn.lock b/code/yarn.lock index 889b85d0ed19..7a4687c53d1e 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -10207,7 +10207,7 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:^0.34.2": +"@vitest/expect@npm:0.34.5": version: 0.34.5 resolution: "@vitest/expect@npm:0.34.5" dependencies: @@ -10218,6 +10218,17 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@patch:@vitest/expect@npm%3A0.34.5#./.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch::locator=%40storybook%2Froot%40workspace%3A.": + version: 0.34.5 + resolution: "@vitest/expect@patch:@vitest/expect@npm%3A0.34.5#./.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch::version=0.34.5&hash=f89b80&locator=%40storybook%2Froot%40workspace%3A." + dependencies: + "@vitest/spy": 0.34.5 + "@vitest/utils": 0.34.5 + chai: ^4.3.7 + checksum: b08f0b1df6a37305f3f68feec15cfac048ca9e3924998698625394296faac4e539e23d7422eec59c0850a83b7342b574a2d2d174aaa33a7eb0004e4e366c515c + languageName: node + linkType: hard + "@vitest/spy@npm:0.34.5": version: 0.34.5 resolution: "@vitest/spy@npm:0.34.5" From d44e0bddb5c9e5684019e824526fd3726dc1ef03 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Sat, 23 Sep 2023 15:43:01 +0200 Subject: [PATCH 035/524] Fix lazy getters --- code/lib/instrumenter/src/instrumenter.ts | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index c9ed517e054a..816e44cc0e66 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -302,19 +302,25 @@ export class Instrumenter { depth += 1; return keys.reduce( (acc, key) => { + const descriptor = getPropertyDescriptor(obj, key); + if (typeof descriptor?.get === 'function') { + Object.defineProperty(acc, key, { + get: () => { + return this.instrument( + (obj as Record)[key], + { ...options, path: path.concat(key) }, + depth + ); + }, + }); + return acc; + } + const value = (obj as Record)[key]; + // Nothing to patch, but might be instrumentable, so we recurse if (typeof value !== 'function') { - const descriptor = getPropertyDescriptor(obj, key); - if (typeof descriptor?.get === 'function') { - Object.defineProperty(acc, key, { - get: () => { - return this.instrument(value, { ...options, path: path.concat(key) }, depth); - }, - }); - } else { - acc[key] = this.instrument(value, { ...options, path: path.concat(key) }, depth); - } + acc[key] = this.instrument(value, { ...options, path: path.concat(key) }, depth); return acc; } From 8657c59aa8d96c74737202a37efee8b8e620618f Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Sat, 23 Sep 2023 15:51:07 +0200 Subject: [PATCH 036/524] Fix gitignore --- .gitignore | 1 + ...@vitest-expect-npm-0.34.5-8031508efe.patch | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 code/.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch diff --git a/.gitignore b/.gitignore index 63f9445af854..0d0e9ac8d8ce 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ test-results !/**/.yarn/plugins !/**/.yarn/sdks !/**/.yarn/versions +!/**/.yarn/patches /**/.pnp.* !/node_modules diff --git a/code/.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch b/code/.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch new file mode 100644 index 000000000000..175c8fbcc343 --- /dev/null +++ b/code/.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch @@ -0,0 +1,37 @@ +diff --git a/dist/index.js b/dist/index.js +index 5a61947ad50426d27390b4e82533179323ad3ba1..32bfc45909b645cb31cec2e204c8baa23f21fdd2 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -6,23 +6,29 @@ import { processError } from '@vitest/utils/error'; + import { util } from 'chai'; + + const MATCHERS_OBJECT = Symbol.for("matchers-object"); +-const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object"); ++// Patched this symbol for storybook, so that @storybook/test can be used in a jest environment as well. ++// Otherwise, vitest will override global jest matchers, and crash. ++const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object-storybook"); + const GLOBAL_EXPECT = Symbol.for("expect-global"); + + if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) { + const globalState = /* @__PURE__ */ new WeakMap(); +- const matchers = /* @__PURE__ */ Object.create(null); + Object.defineProperty(globalThis, MATCHERS_OBJECT, { + get: () => globalState + }); ++} ++ ++if (!Object.prototype.hasOwnProperty.call(globalThis, JEST_MATCHERS_OBJECT)) { ++ const matchers = /* @__PURE__ */ Object.create(null); + Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, { + configurable: true, + get: () => ({ +- state: globalState.get(globalThis[GLOBAL_EXPECT]), ++ state: globalThis[MATCHERS_OBJECT].get(globalThis[GLOBAL_EXPECT]), + matchers + }) + }); + } ++ + function getState(expect) { + return globalThis[MATCHERS_OBJECT].get(expect); + } From a5cdd3194b4f07fb8cbeeeab64970250a9d224ee Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 3 Oct 2023 11:36:26 +0200 Subject: [PATCH 037/524] Fix getter --- code/lib/instrumenter/src/instrumenter.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 816e44cc0e66..47d501770d5b 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -304,13 +304,10 @@ export class Instrumenter { (acc, key) => { const descriptor = getPropertyDescriptor(obj, key); if (typeof descriptor?.get === 'function') { + const getter = () => descriptor?.get?.(); Object.defineProperty(acc, key, { get: () => { - return this.instrument( - (obj as Record)[key], - { ...options, path: path.concat(key) }, - depth - ); + return this.instrument(getter(), { ...options, path: path.concat(key) }, depth); }, }); return acc; From de86f5d737d9a2b0875daf186dbc372acdcbbec2 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 4 Oct 2023 12:38:14 +0200 Subject: [PATCH 038/524] Always externalize @vitest deps in tsup, as they are ESM-only. But still use it for the dts files, as bundling dts files is buggy --- code/lib/test/package.json | 13 ++++++------- code/yarn.lock | 1 - scripts/prepare/bundle.ts | 4 ++++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/code/lib/test/package.json b/code/lib/test/package.json index 728bb3674f35..7de3167917c8 100644 --- a/code/lib/test/package.json +++ b/code/lib/test/package.json @@ -50,18 +50,17 @@ "@testing-library/dom": "^9.3.1", "@testing-library/jest-dom": "^6.1.3", "@testing-library/user-event": "^14.4.3", + "@types/chai": "^4", + "@vitest/expect": "^0.34.2", + "@vitest/spy": "^0.34.1", "chai": "^4.3.7", "expect": "^29.6.2", - "loupe": "^2.3.1", - "ts-dedent": "^2.2.0" + "ts-dedent": "^2.2.0", + "util": "^0.12.4" }, "devDependencies": { - "@types/chai": "^4", - "@vitest/expect": "^0.34.2", - "@vitest/spy": "^0.34.1", "type-fest": "~2.19", - "typescript": "~4.9.3", - "util": "^0.12.4" + "typescript": "~4.9.3" }, "publishConfig": { "access": "public" diff --git a/code/yarn.lock b/code/yarn.lock index 78fecc29b567..4bc78dab3ce9 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -8122,7 +8122,6 @@ __metadata: "@vitest/spy": ^0.34.1 chai: ^4.3.7 expect: ^29.6.2 - loupe: ^2.3.1 ts-dedent: ^2.2.0 type-fest: ~2.19 typescript: ~4.9.3 diff --git a/scripts/prepare/bundle.ts b/scripts/prepare/bundle.ts index a15f71cd6a34..02199ecff992 100755 --- a/scripts/prepare/bundle.ts +++ b/scripts/prepare/bundle.ts @@ -79,9 +79,12 @@ const run = async ({ cwd, flags }: { cwd: string; flags: string[] }) => { */ const nonPresetEntries = allEntries.filter((f) => !path.parse(f).name.includes('preset')); + const noExternal = [/^@vitest\/.+$/]; + if (formats.includes('esm')) { tasks.push( build({ + noExternal, silent: true, treeshake: true, entry: nonPresetEntries, @@ -116,6 +119,7 @@ const run = async ({ cwd, flags }: { cwd: string; flags: string[] }) => { if (formats.includes('cjs')) { tasks.push( build({ + noExternal, silent: true, entry: allEntries, watch, From 6ee27f2b7d52bb55bf120ef0f2953eb74d44d6f6 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 3 Oct 2023 15:17:26 +0200 Subject: [PATCH 039/524] Always install extra deps --- scripts/tasks/sandbox-parts.ts | 7 ++----- scripts/tasks/sandbox.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index e6b1bc188fd4..393169b244f8 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -354,7 +354,7 @@ async function linkPackageStories( ); } -async function addExtraDependencies({ +export async function addExtraDependencies({ cwd, dryRun, debug, @@ -378,7 +378,7 @@ async function addExtraDependencies({ export const addStories: Task['run'] = async ( { sandboxDir, template, key }, - { addon: extraAddons, dryRun, debug, disableDocs } + { addon: extraAddons, disableDocs } ) => { logger.log('💃 adding stories'); const cwd = sandboxDir; @@ -516,9 +516,6 @@ export const addStories: Task['run'] = async ( } } - // Some addon stories require extra dependencies - await addExtraDependencies({ cwd, dryRun, debug }); - await writeConfig(mainConfig); }; diff --git a/scripts/tasks/sandbox.ts b/scripts/tasks/sandbox.ts index 24b946049631..30f78137b586 100644 --- a/scripts/tasks/sandbox.ts +++ b/scripts/tasks/sandbox.ts @@ -37,7 +37,9 @@ export const sandbox: Task = { await remove(details.sandboxDir); } - const { create, install, addStories, extendMain, init } = await import('./sandbox-parts'); + const { create, install, addStories, extendMain, init, addExtraDependencies } = await import( + './sandbox-parts' + ); let startTime = now(); await create(details, options); @@ -72,6 +74,12 @@ export const sandbox: Task = { await addStories(details, options); } + await addExtraDependencies({ + cwd: details.sandboxDir, + debug: options.debug, + dryRun: options.dryRun, + }); + await extendMain(details, options); logger.info(`✅ Storybook sandbox created at ${details.sandboxDir}`); From 47586d92d13168fa4cdceeb2f6738bb9633c39ec Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 4 Oct 2023 13:48:55 +0200 Subject: [PATCH 040/524] Fix getters that use `this` --- code/lib/instrumenter/src/instrumenter.ts | 2 +- code/lib/test/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts index 47d501770d5b..de7914f3d64a 100644 --- a/code/lib/instrumenter/src/instrumenter.ts +++ b/code/lib/instrumenter/src/instrumenter.ts @@ -304,7 +304,7 @@ export class Instrumenter { (acc, key) => { const descriptor = getPropertyDescriptor(obj, key); if (typeof descriptor?.get === 'function') { - const getter = () => descriptor?.get?.(); + const getter = () => descriptor?.get?.bind(obj)?.(); Object.defineProperty(acc, key, { get: () => { return this.instrument(getter(), { ...options, path: path.concat(key) }, depth); diff --git a/code/lib/test/src/index.ts b/code/lib/test/src/index.ts index 7b832fb052e9..34d59391676e 100644 --- a/code/lib/test/src/index.ts +++ b/code/lib/test/src/index.ts @@ -18,7 +18,7 @@ export const { expect } = instrument( { expect: rawExpect }, { getKeys: (obj: Record, depth) => { - const privateApi = ['assert', '__methods', '__flags']; + const privateApi = ['assert', '__methods', '__flags', '_obj']; if (obj.constructor === chai.Assertion) { const keys = Object.keys(Object.getPrototypeOf(obj)).filter( (it) => !privateApi.includes(it) From 4ae6a7765affd710609f5984ed862d32c5d6e2ef Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Wed, 4 Oct 2023 13:52:22 +0200 Subject: [PATCH 041/524] Fix deps issue --- code/ui/manager/package.json | 1 + code/yarn.lock | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/code/ui/manager/package.json b/code/ui/manager/package.json index 36960bd3baa2..5aa73a6c5779 100644 --- a/code/ui/manager/package.json +++ b/code/ui/manager/package.json @@ -61,6 +61,7 @@ "@storybook/global": "^5.0.0", "@storybook/manager-api": "workspace:*", "@storybook/router": "workspace:*", + "@storybook/test": "workspace:*", "@storybook/theming": "workspace:*", "@storybook/types": "workspace:*", "@testing-library/react": "^11.2.2", diff --git a/code/yarn.lock b/code/yarn.lock index 4bc78dab3ce9..9110bc9020c8 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -7212,6 +7212,7 @@ __metadata: "@storybook/global": ^5.0.0 "@storybook/manager-api": "workspace:*" "@storybook/router": "workspace:*" + "@storybook/test": "workspace:*" "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@testing-library/react": ^11.2.2 @@ -8106,7 +8107,7 @@ __metadata: languageName: unknown linkType: soft -"@storybook/test@workspace:lib/test": +"@storybook/test@workspace:*, @storybook/test@workspace:lib/test": version: 0.0.0-use.local resolution: "@storybook/test@workspace:lib/test" dependencies: From 6de0d4919974b7fe41befb01c8d8eda53364dedb Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 5 Oct 2023 15:40:55 +0200 Subject: [PATCH 042/524] Fix lock files --- code/yarn.lock | 196 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 189 insertions(+), 7 deletions(-) diff --git a/code/yarn.lock b/code/yarn.lock index 3ec46c6397a8..d879303d9c2a 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -24,7 +24,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1": +"@adobe/css-tools@npm:^4.0.1, @adobe/css-tools@npm:^4.3.0": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: 05672719b544cc0c21ae3ed0eb6349bf458e9d09457578eeeb07cf0f696469ac6417e9c9be1b129e5d6a18098a061c1db55b2275591760ef30a79822436fcbfa @@ -7206,6 +7206,7 @@ __metadata: "@storybook/global": ^5.0.0 "@storybook/manager-api": "workspace:*" "@storybook/router": "workspace:*" + "@storybook/test": "workspace:*" "@storybook/theming": "workspace:*" "@storybook/types": "workspace:*" "@testing-library/react": ^11.2.2 @@ -8099,6 +8100,29 @@ __metadata: languageName: unknown linkType: soft +"@storybook/test@workspace:*, @storybook/test@workspace:lib/test": + version: 0.0.0-use.local + resolution: "@storybook/test@workspace:lib/test" + dependencies: + "@storybook/client-logger": "workspace:*" + "@storybook/core-events": "workspace:*" + "@storybook/instrumenter": "workspace:*" + "@storybook/preview-api": "workspace:*" + "@testing-library/dom": ^9.3.1 + "@testing-library/jest-dom": ^6.1.3 + "@testing-library/user-event": ^14.4.3 + "@types/chai": ^4 + "@vitest/expect": ^0.34.2 + "@vitest/spy": ^0.34.1 + chai: ^4.3.7 + expect: ^29.6.2 + ts-dedent: ^2.2.0 + type-fest: ~2.19 + typescript: ~4.9.3 + util: ^0.12.4 + languageName: unknown + linkType: soft + "@storybook/testing-library@npm:next": version: 0.2.2-next.0 resolution: "@storybook/testing-library@npm:0.2.2-next.0" @@ -8694,7 +8718,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:^9.0.0": +"@testing-library/dom@npm:^9.0.0, @testing-library/dom@npm:^9.3.1": version: 9.3.3 resolution: "@testing-library/dom@npm:9.3.3" dependencies: @@ -8727,6 +8751,36 @@ __metadata: languageName: node linkType: hard +"@testing-library/jest-dom@npm:^6.1.2, @testing-library/jest-dom@npm:^6.1.3": + version: 6.1.3 + resolution: "@testing-library/jest-dom@npm:6.1.3" + dependencies: + "@adobe/css-tools": ^4.3.0 + "@babel/runtime": ^7.9.2 + aria-query: ^5.0.0 + chalk: ^3.0.0 + css.escape: ^1.5.1 + dom-accessibility-api: ^0.5.6 + lodash: ^4.17.15 + redent: ^3.0.0 + peerDependencies: + "@jest/globals": ">= 28" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: 544e01939d3c14a3d44ae2e2bb9fe2a0cb5a9e4992ca2728f41188fb9fb2d56e25f1a2e1c12000be2a94d8da36cb220b24020e1b5c5c4c4bede9058a0d80583d + languageName: node + linkType: hard + "@testing-library/react@npm:^11.2.2": version: 11.2.7 resolution: "@testing-library/react@npm:11.2.7" @@ -8751,7 +8805,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/user-event@npm:^14.4.0": +"@testing-library/user-event@npm:^14.4.0, @testing-library/user-event@npm:^14.4.3": version: 14.5.1 resolution: "@testing-library/user-event@npm:14.5.1" peerDependencies: @@ -8928,6 +8982,13 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^4": + version: 4.3.6 + resolution: "@types/chai@npm:4.3.6" + checksum: 388af382b11453a69808800479dcaff0323a0d1e15df1619175ebd55b294d716d560058f560ed55434e8846af46f017d7d78544822571f6322d3fac6d5f8a29d + languageName: node + linkType: hard + "@types/cheerio@npm:^0.22.22": version: 0.22.32 resolution: "@types/cheerio@npm:0.22.32" @@ -10140,6 +10201,57 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:0.34.5": + version: 0.34.5 + resolution: "@vitest/expect@npm:0.34.5" + dependencies: + "@vitest/spy": 0.34.5 + "@vitest/utils": 0.34.5 + chai: ^4.3.7 + checksum: dc30a5e1f2732a1906df57f65381df1129dbf994496734c27e4a3f832852862501eaba1ec2987215ec12ee23a8f2ef1d8ff63c7cd5490046a7a26800da1adcb2 + languageName: node + linkType: hard + +"@vitest/expect@patch:@vitest/expect@npm%3A0.34.5#./.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch::locator=%40storybook%2Froot%40workspace%3A.": + version: 0.34.5 + resolution: "@vitest/expect@patch:@vitest/expect@npm%3A0.34.5#./.yarn/patches/@vitest-expect-npm-0.34.5-8031508efe.patch::version=0.34.5&hash=f89b80&locator=%40storybook%2Froot%40workspace%3A." + dependencies: + "@vitest/spy": 0.34.5 + "@vitest/utils": 0.34.5 + chai: ^4.3.7 + checksum: b08f0b1df6a37305f3f68feec15cfac048ca9e3924998698625394296faac4e539e23d7422eec59c0850a83b7342b574a2d2d174aaa33a7eb0004e4e366c515c + languageName: node + linkType: hard + +"@vitest/spy@npm:0.34.5": + version: 0.34.5 + resolution: "@vitest/spy@npm:0.34.5" + dependencies: + tinyspy: ^2.1.1 + checksum: bbee495ca6300f50dde6418d14db0d3281daf38df15abae95202ddef253d6dd8bedf9f4a79da5a2246d3758ab24aa737caccf752fabcd8ba902a4f14801c2a0c + languageName: node + linkType: hard + +"@vitest/spy@npm:^0.34.1": + version: 0.34.7 + resolution: "@vitest/spy@npm:0.34.7" + dependencies: + tinyspy: ^2.1.1 + checksum: 1150b270eb72a5e8e7da997bcba90ebe5ed2ac50de1ea1f81738e16a19ab4bc77ca4d17639988df65695d4b325fe3647a1e4204d01024bcf5ecac8ba7764a2cc + languageName: node + linkType: hard + +"@vitest/utils@npm:0.34.5": + version: 0.34.5 + resolution: "@vitest/utils@npm:0.34.5" + dependencies: + diff-sequences: ^29.4.3 + loupe: ^2.3.6 + pretty-format: ^29.5.0 + checksum: 99cc5974ada1dab2b02220005c0fc97147baba175601a0faa1b2b6687c7f579d21a401077377d6f759b3aa8a07dcc8851cdc3e07f9a550ec289286107487ac36 + languageName: node + linkType: hard + "@volar/language-core@npm:1.10.1, @volar/language-core@npm:~1.10.0": version: 1.10.1 resolution: "@volar/language-core@npm:1.10.1" @@ -11465,6 +11577,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: 25456b2aa333250f01143968e02e4884a34588a8538fbbf65c91a637f1dbfb8069249133cd2f4e530f10f624d206a664e7df30207830b659e9f5298b00a4099b + languageName: node + linkType: hard + "assign-symbols@npm:^1.0.0": version: 1.0.0 resolution: "assign-symbols@npm:1.0.0" @@ -12893,6 +13012,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.7": + version: 4.3.10 + resolution: "chai@npm:4.3.10" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.0.8 + checksum: c887d24f67be6fb554c7ebbde3bb0568697a8833d475e4768296916891ba143f25fc079f6eb34146f3dd5a3279d34c1f387c32c9a6ab288e579f948d9ccf53fe + languageName: node + linkType: hard + "chalk@npm:4.1.0": version: 4.1.0 resolution: "chalk@npm:4.1.0" @@ -13020,6 +13154,15 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: 94aa37a7315c0e8a83d0112b5bfb5a8624f7f0f81057c73e4707729cdd8077166c6aefb3d8e2b92c63ee130d4a2ff94bad46d547e12f3238cc1d78342a973841 + languageName: node + linkType: hard + "checkup@npm:^1.3.0": version: 1.3.0 resolution: "checkup@npm:1.3.0" @@ -14517,6 +14660,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: ^4.0.0 + checksum: ff34e8605d8253e1bf9fe48056e02c6f347b81d9b5df1c6650a1b0f6f847b4a86453b16dc226b34f853ef14b626e85d04e081b022e20b00cd7d54f079ce9bbdd + languageName: node + linkType: hard + "deep-equal@npm:^1.1.1": version: 1.1.1 resolution: "deep-equal@npm:1.1.1" @@ -14830,7 +14982,7 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^29.6.3": +"diff-sequences@npm:^29.4.3, diff-sequences@npm:^29.6.3": version: 29.6.3 resolution: "diff-sequences@npm:29.6.3" checksum: 32e27ac7dbffdf2fb0eb5a84efd98a9ad084fbabd5ac9abb8757c6770d5320d2acd172830b28c4add29bb873d59420601dfc805ac4064330ce59b1adfd0593b2 @@ -16696,7 +16848,7 @@ __metadata: languageName: node linkType: hard -"expect@npm:^29.0.0, expect@npm:^29.7.0": +"expect@npm:^29.0.0, expect@npm:^29.6.2, expect@npm:^29.7.0": version: 29.7.0 resolution: "expect@npm:29.7.0" dependencies: @@ -17788,6 +17940,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.0, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 89830fd07623fa73429a711b9daecdb304386d237c71268007f788f113505ef1d4cc2d0b9680e072c5082490aec9df5d7758bf5ac6f1c37062855e8e3dc0b9df + languageName: node + linkType: hard + "get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1": version: 1.2.1 resolution: "get-intrinsic@npm:1.2.1" @@ -22142,6 +22301,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6": + version: 2.3.6 + resolution: "loupe@npm:2.3.6" + dependencies: + get-func-name: ^2.0.0 + checksum: a974841ce94ef2a35aac7144e7f9e789e3887f82286cd9ffe7ff00f2ac9d117481989948657465e2b0b102f23136d89ae0a18fd4a32d9015012cd64464453289 + languageName: node + linkType: hard + "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -25622,6 +25790,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: f63e1bc1b33593cdf094ed6ff5c49c1c0dc5dc20a646ca9725cc7fe7cd9995002d51d5685b9b2ec6814342935748b711bafa840f84c0bb04e38ff40a335c94dc + languageName: node + linkType: hard + "pbkdf2@npm:^3.0.3": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" @@ -26223,7 +26398,7 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.5.0, pretty-format@npm:^29.7.0": version: 29.7.0 resolution: "pretty-format@npm:29.7.0" dependencies: @@ -30430,6 +30605,13 @@ __metadata: languageName: node linkType: hard +"tinyspy@npm:^2.1.1": + version: 2.2.0 + resolution: "tinyspy@npm:2.2.0" + checksum: 8c7b70748dd8590e85d52741db79243746c15bc03c92d75c23160a762142db577e7f53e360ba7300e321b12bca5c42dd2522a8dbeec6ba3830302573dd8516bc + languageName: node + linkType: hard + "tmp@npm:0.0.28": version: 0.0.28 resolution: "tmp@npm:0.0.28" @@ -30881,7 +31063,7 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8": +"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 8fb9a51d3f365a7de84ab7f73b653534b61b622aa6800aecdb0f1095a4a646d3f5eb295322127b6573db7982afcd40ab492d038cf825a42093a58b1e1353e0bd From 2b9981a9193563a44ca69ce91bad3a5bc8db8996 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Thu, 5 Oct 2023 15:45:56 +0200 Subject: [PATCH 043/524] Fix check script --- code/ui/blocks/src/blocks/internal/InternalCanvas.stories.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/code/ui/blocks/src/blocks/internal/InternalCanvas.stories.tsx b/code/ui/blocks/src/blocks/internal/InternalCanvas.stories.tsx index fb0f444720c3..b45015c94b50 100644 --- a/code/ui/blocks/src/blocks/internal/InternalCanvas.stories.tsx +++ b/code/ui/blocks/src/blocks/internal/InternalCanvas.stories.tsx @@ -1,5 +1,4 @@ /// ; -/// ; import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { userEvent, within } from '@storybook/testing-library'; From f523d0d9f9e107e562bb1f5b495451633ae210da Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 5 Oct 2023 09:52:28 -0400 Subject: [PATCH 044/524] Themes: Run postinstall in shell for windows --- code/addons/themes/postinstall.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/code/addons/themes/postinstall.js b/code/addons/themes/postinstall.js index 01a9b3151e89..6292d2f00b9a 100644 --- a/code/addons/themes/postinstall.js +++ b/code/addons/themes/postinstall.js @@ -1,17 +1,29 @@ const { spawn } = require('child_process'); const PACKAGE_MANAGER_TO_COMMAND = { - npm: 'npx', - yarn1: 'npx', - yarn2: 'yarn dlx', - pnpm: 'pnpm dlx', + npm: ['npx'], + pnpm: ['pnpm', 'dlx'], + yarn1: ['npx'], + yarn2: ['yarn', 'dlx'], }; -module.exports = function postinstall(options) { - const command = PACKAGE_MANAGER_TO_COMMAND[options.packageManager]; +const selectPackageManagerCommand = (packageManager) => PACKAGE_MANAGER_TO_COMMAND[packageManager]; - spawn(command, ['@storybook/auto-config', 'themes'], { +const spawnPackageManagerScript = async (packageManager, args) => { + const [command, ...baseArgs] = selectPackageManagerCommand(packageManager); + + await spawn(command, [...baseArgs, ...args], { stdio: 'inherit', cwd: process.cwd(), + shell: true, }); }; + +module.exports = async function postinstall({ packageManager = 'npm' }) { + try { + await spawnPackageManagerScript(packageManager, ['@storybook/auto-config', 'themes']); + } catch (e) { + console.error(e); + process.exit(1); + } +}; From d9ee6623aa6ce176e9894a8f8d6a94a806b7ada7 Mon Sep 17 00:00:00 2001 From: Shaun Lloyd Date: Thu, 5 Oct 2023 10:39:21 -0400 Subject: [PATCH 045/524] Let error bubble up --- code/addons/themes/postinstall.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/addons/themes/postinstall.js b/code/addons/themes/postinstall.js index 6292d2f00b9a..87175ac9cbc1 100644 --- a/code/addons/themes/postinstall.js +++ b/code/addons/themes/postinstall.js @@ -20,10 +20,5 @@ const spawnPackageManagerScript = async (packageManager, args) => { }; module.exports = async function postinstall({ packageManager = 'npm' }) { - try { - await spawnPackageManagerScript(packageManager, ['@storybook/auto-config', 'themes']); - } catch (e) { - console.error(e); - process.exit(1); - } + await spawnPackageManagerScript(packageManager, ['@storybook/auto-config', 'themes']); }; From d4bf6448f1775b9365f54ba2619fd90e5d17ca21 Mon Sep 17 00:00:00 2001 From: Dee Bryant Date: Sat, 7 Oct 2023 17:07:37 +1100 Subject: [PATCH 046/524] fix(a11y): remove redundant styling rules, update icon colour, fix alignment --- code/addons/a11y/src/components/Report/Item.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/code/addons/a11y/src/components/Report/Item.tsx b/code/addons/a11y/src/components/Report/Item.tsx index 94a92f26a0ff..2d34ee58d745 100644 --- a/code/addons/a11y/src/components/Report/Item.tsx +++ b/code/addons/a11y/src/components/Report/Item.tsx @@ -21,16 +21,14 @@ const Wrapper = styled.div(({ theme }) => ({ }, })); -const Icon = styled(Icons)(({ theme }) => ({ +const Icon = styled(Icons)({ height: 10, width: 10, minWidth: 10, - color: theme.textMutedColor, marginRight: 10, transition: 'transform 0.1s ease-in-out', - alignSelf: 'center', - display: 'inline-flex', -})); + verticalAlign: 'inherit', +}); const HeaderBar = styled.div(({ theme }) => ({ padding: theme.layoutMargin, @@ -78,7 +76,6 @@ export const Item = (props: ItemProps) => { onToggle(!open)} role="button"> Date: Mon, 9 Oct 2023 16:23:47 +0900 Subject: [PATCH 047/524] fix: remove negative margin when layout is centered or padded --- code/ui/blocks/src/components/Preview.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/code/ui/blocks/src/components/Preview.tsx b/code/ui/blocks/src/components/Preview.tsx index 18306e8e4da9..a4651ba72184 100644 --- a/code/ui/blocks/src/components/Preview.tsx +++ b/code/ui/blocks/src/components/Preview.tsx @@ -52,7 +52,6 @@ const ChildrenContainer = styled.div( layout === 'centered' || layout === 'padded' ? { padding: '30px 20px', - margin: -10, '& .innerZoomElementWrapper > *': { width: 'auto', border: '10px solid transparent!important', From fb8461369a7ad77d9c27acb301bde53db4475ba6 Mon Sep 17 00:00:00 2001 From: Kasper Peulen Date: Tue, 10 Oct 2023 10:18:18 +0200 Subject: [PATCH 048/524] Calculate the diff for chai errors --- .../src/components/Interaction.tsx | 25 ++++++++++++++++++- .../src/components/MatcherResult.tsx | 9 ++++++- code/lib/instrumenter/package.json | 4 ++- code/lib/instrumenter/src/instrumenter.ts | 12 ++++++++- code/lib/instrumenter/src/types.ts | 4 +++ code/yarn.lock | 13 ++++++++++ 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/code/addons/interactions/src/components/Interaction.tsx b/code/addons/interactions/src/components/Interaction.tsx index bacaea0fe358..af2bea6bd20b 100644 --- a/code/addons/interactions/src/components/Interaction.tsx +++ b/code/addons/interactions/src/components/Interaction.tsx @@ -4,7 +4,7 @@ import { type Call, CallStates, type ControlStates } from '@storybook/instrument import { styled, typography } from '@storybook/theming'; import { transparentize } from 'polished'; -import { MatcherResult } from './MatcherResult'; +import { Expected, MatcherResult, Received } from './MatcherResult'; import { MethodCall } from './MethodCall'; import { StatusIcon } from './StatusIcon'; @@ -120,6 +120,29 @@ const Exception = ({ exception }: { exception: Call['exception'] }) => { return (
{paragraphs[0]}
+ + {exception.showDiff && exception.diff ? ( + <> +
+ + + ) : ( +
+          
+ {exception.expected && ( + <> + Expected: +
+ + )} + {exception.actual && ( + <> + Received: +
+ + )} +
+ )} {more &&

See the full stack trace in the browser console.

}
); diff --git a/code/addons/interactions/src/components/MatcherResult.tsx b/code/addons/interactions/src/components/MatcherResult.tsx index a8a1e00a63f7..6f1d8aef9f1d 100644 --- a/code/addons/interactions/src/components/MatcherResult.tsx +++ b/code/addons/interactions/src/components/MatcherResult.tsx @@ -45,7 +45,13 @@ export const Expected = ({ value, parsed }: { value: any; parsed?: boolean }) => return {value}; }; -export const MatcherResult = ({ message }: { message: string }) => { +export const MatcherResult = ({ + message, + style = {}, +}: { + message: string; + style?: React.CSSProperties; +}) => { const lines = message.split('\n'); return (
 {
         margin: 0,
         padding: '8px 10px 8px 36px',
         fontSize: typography.size.s1,
+        ...style,
       }}
     >
       {lines.flatMap((line: string, index: number) => {
diff --git a/code/lib/instrumenter/package.json b/code/lib/instrumenter/package.json
index b9d22eb8445f..aae6b577f111 100644
--- a/code/lib/instrumenter/package.json
+++ b/code/lib/instrumenter/package.json
@@ -48,7 +48,9 @@
     "@storybook/client-logger": "workspace:*",
     "@storybook/core-events": "workspace:*",
     "@storybook/global": "^5.0.0",
-    "@storybook/preview-api": "workspace:*"
+    "@storybook/preview-api": "workspace:*",
+    "@vitest/utils": "^0.34.6",
+    "util": "^0.12.4"
   },
   "devDependencies": {
     "typescript": "~4.9.3"
diff --git a/code/lib/instrumenter/src/instrumenter.ts b/code/lib/instrumenter/src/instrumenter.ts
index de7914f3d64a..0ffaa0ca0d5f 100644
--- a/code/lib/instrumenter/src/instrumenter.ts
+++ b/code/lib/instrumenter/src/instrumenter.ts
@@ -10,6 +10,7 @@ import {
   STORY_RENDER_PHASE_CHANGED,
 } from '@storybook/core-events';
 import { global } from '@storybook/global';
+import { processError } from '@vitest/utils/error';
 
 import type { Call, CallRef, ControlStates, LogItem, Options, State, SyncPayload } from './types';
 import { CallStates } from './types';
@@ -466,7 +467,16 @@ export class Instrumenter {
     const handleException = (e: any) => {
       if (e instanceof Error) {
         const { name, message, stack, callId = call.id } = e as Error & { callId: Call['id'] };
-        const exception = { name, message, stack, callId };
+
+        // This will calculate the diff for chai errors
+        const {
+          showDiff = undefined,
+          diff = undefined,
+          actual = undefined,
+          expected = undefined,
+        } = processError(e);
+
+        const exception = { name, message, stack, callId, showDiff, diff, actual, expected };
         this.update({ ...info, status: CallStates.ERROR, exception });
 
         // Always track errors to their originating call.
diff --git a/code/lib/instrumenter/src/types.ts b/code/lib/instrumenter/src/types.ts
index 0a528a5c161a..f3a2ee274200 100644
--- a/code/lib/instrumenter/src/types.ts
+++ b/code/lib/instrumenter/src/types.ts
@@ -16,6 +16,10 @@ export interface Call {
     message: Error['message'];
     stack: Error['stack'];
     callId: Call['id'];
+    showDiff?: boolean;
+    diff?: string;
+    actual?: unknown;
+    expected?: unknown;
   };
 }
 
diff --git a/code/yarn.lock b/code/yarn.lock
index d879303d9c2a..90c5acfda7fb 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -7118,7 +7118,9 @@ __metadata:
     "@storybook/core-events": "workspace:*"
     "@storybook/global": ^5.0.0
     "@storybook/preview-api": "workspace:*"
+    "@vitest/utils": ^0.34.6
     typescript: ~4.9.3
+    util: ^0.12.4
   languageName: unknown
   linkType: soft
 
@@ -10252,6 +10254,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@vitest/utils@npm:^0.34.6":
+  version: 0.34.7
+  resolution: "@vitest/utils@npm:0.34.7"
+  dependencies:
+    diff-sequences: ^29.4.3
+    loupe: ^2.3.6
+    pretty-format: ^29.5.0
+  checksum: 5f26ec5b4a53709a50efdb57aa753e8090b3411e888774f67a0d192eb7f046ed5fcc6884eb3d6275d2674926e724b731e8d28cd3cea96a7f3d27462a0d44af9e
+  languageName: node
+  linkType: hard
+
 "@volar/language-core@npm:1.10.1, @volar/language-core@npm:~1.10.0":
   version: 1.10.1
   resolution: "@volar/language-core@npm:1.10.1"

From 6801e046e0e12a02132fcbe62deb99e30427d44b Mon Sep 17 00:00:00 2001
From: Kasper Peulen 
Date: Tue, 10 Oct 2023 11:58:55 +0200
Subject: [PATCH 049/524] Add moduleNameMapper for ESM only modules with
 package json exports

---
 code/jest.config.base.js                       | 2 ++
 code/lib/instrumenter/src/instrumenter.test.ts | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/code/jest.config.base.js b/code/jest.config.base.js
index 59cb8cf3c37e..89ff7acf0b8b 100644
--- a/code/jest.config.base.js
+++ b/code/jest.config.base.js
@@ -61,6 +61,8 @@ module.exports = {
       path.resolve('./__mocks__/fileMock.js'),
     '\\.(css|scss|stylesheet)$': path.resolve('./__mocks__/styleMock.js'),
     '\\.(md)$': path.resolve('./__mocks__/htmlMock.js'),
+    '@vitest/utils/(.*)': '@vitest/utils/dist/$1.js',
+    '@vitest/utils': '@vitest/utils/dist/index.js',
   },
   transform: {
     '^.+\\.(t|j)sx?$': ['@swc/jest', swcrc],
diff --git a/code/lib/instrumenter/src/instrumenter.test.ts b/code/lib/instrumenter/src/instrumenter.test.ts
index 184c6773a747..35f0b6a87830 100644
--- a/code/lib/instrumenter/src/instrumenter.test.ts
+++ b/code/lib/instrumenter/src/instrumenter.test.ts
@@ -548,12 +548,12 @@ describe('Instrumenter', () => {
       expect(callSpy).toHaveBeenCalledWith(
         expect.objectContaining({
           id: 'kind--story [0] fn',
-          exception: {
+          exception: expect.objectContaining({
             name: 'Error',
             message: 'Boom!',
             stack: expect.stringContaining('Error: Boom!'),
             callId: 'kind--story [0] fn',
-          },
+          }),
         })
       );
     });

From ef847b9bf1b7ec56cabfed1f431ab0e28dba2f47 Mon Sep 17 00:00:00 2001
From: Kasper Peulen 
Date: Tue, 10 Oct 2023 15:50:27 +0200
Subject: [PATCH 050/524] Downcast function types that are mocks in meta args

---
 code/renderers/react/package.json             |  1 +
 .../renderers/react/src/public-types.test.tsx | 28 +++++++++++++++++++
 code/renderers/react/src/public-types.ts      | 12 +++++++-
 code/yarn.lock                                |  1 +
 4 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/code/renderers/react/package.json b/code/renderers/react/package.json
index 75c51405d7e7..87a83b58abd5 100644
--- a/code/renderers/react/package.json
+++ b/code/renderers/react/package.json
@@ -77,6 +77,7 @@
   },
   "devDependencies": {
     "@babel/core": "^7.22.9",
+    "@storybook/test": "workspace:*",
     "@types/util-deprecate": "^1.0.0",
     "expect-type": "^0.15.0",
     "jest-specific-snapshot": "^8.0.0",
diff --git a/code/renderers/react/src/public-types.test.tsx b/code/renderers/react/src/public-types.test.tsx
index 1fc3fd15d10c..ea4beb7810c0 100644
--- a/code/renderers/react/src/public-types.test.tsx
+++ b/code/renderers/react/src/public-types.test.tsx
@@ -7,6 +7,8 @@ import type { KeyboardEventHandler, ReactNode } from 'react';
 import React from 'react';
 
 import type { SetOptional } from 'type-fest';
+import type { Mock } from '@storybook/test';
+import { fn } from '@storybook/test';
 
 import type { Decorator, Meta, StoryObj } from './public-types';
 import type { ReactRenderer } from './types';
@@ -300,3 +302,29 @@ test('Meta is broken when using discriminating types, issue #23629', () => {
     },
   }).toMatchTypeOf>();
 });
+
+test('Infer mock function given to args in meta.', () => {
+  type Props = { label: string; onClick: () => void; onRender: () => JSX.Element };
+  const TestButton = (props: Props) => <>;
+
+  const meta = {
+    component: TestButton,
+    args: { label: 'label', onClick: fn(), onRender: () => <>some jsx },
+  } satisfies Meta;
+
+  type Story = StoryObj;
+
+  const Basic: Story = {
+    play: async ({ args }) => {
+      expectTypeOf(args.onClick).toEqualTypeOf>();
+      expectTypeOf(args.onRender).toEqualTypeOf<() => JSX.Element>();
+    },
+  };
+  type Expected = StoryAnnotations<
+    ReactRenderer,
+    Props & { onClick: Mock<[], void> },
+    Partial
+  >;
+
+  expectTypeOf(Basic).toEqualTypeOf();
+});
diff --git a/code/renderers/react/src/public-types.ts b/code/renderers/react/src/public-types.ts
index 592b82b03ff9..95ad7111a3ea 100644
--- a/code/renderers/react/src/public-types.ts
+++ b/code/renderers/react/src/public-types.ts
@@ -56,7 +56,7 @@ export type StoryObj = [TMetaOrCmpOrArgs] extends [
     > extends infer TArgs
     ? StoryAnnotations<
         ReactRenderer,
-        TArgs,
+        AddMocks,
         SetOptional)>
       >
     : never
@@ -64,6 +64,16 @@ export type StoryObj = [TMetaOrCmpOrArgs] extends [
   ? StoryAnnotations>
   : StoryAnnotations;
 
+// This performs a downcast to function types that are mocks, when a mock fn is given to meta args.
+type AddMocks = Simplify<{
+  [T in keyof TArgs]: T extends keyof DefaultArgs
+    ? // eslint-disable-next-line @typescript-eslint/ban-types
+      DefaultArgs[T] extends (...args: any) => any & { mock: {} } // allow any function with a mock object
+      ? DefaultArgs[T]
+      : TArgs[T]
+    : TArgs[T];
+}>;
+
 type ActionArgs = {
   // This can be read as: filter TArgs on functions where we can assign a void function to that function.
   // The docs addon argsEnhancers can only safely provide a default value for void functions.
diff --git a/code/yarn.lock b/code/yarn.lock
index 90c5acfda7fb..da0b6702494c 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -7705,6 +7705,7 @@ __metadata:
     "@storybook/global": ^5.0.0
     "@storybook/preview-api": "workspace:*"
     "@storybook/react-dom-shim": "workspace:*"
+    "@storybook/test": "workspace:*"
     "@storybook/types": "workspace:*"
     "@types/escodegen": ^0.0.6
     "@types/estree": ^0.0.51

From ad10877503e3b15296f54d7c0c654956ab6f011a Mon Sep 17 00:00:00 2001
From: Daniel Marcano 
Date: Mon, 9 Oct 2023 18:37:08 +0200
Subject: [PATCH 051/524] fix: modify BooleanControl so that screen readers
 read a more accurate label, and update its interaction tests

---
 .../blocks/src/controls/Boolean.stories.tsx   | 20 ++++++++++++-------
 code/ui/blocks/src/controls/Boolean.tsx       | 16 +++++++++++----
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/code/ui/blocks/src/controls/Boolean.stories.tsx b/code/ui/blocks/src/controls/Boolean.stories.tsx
index 001a13dcaef7..dee3291f3684 100644
--- a/code/ui/blocks/src/controls/Boolean.stories.tsx
+++ b/code/ui/blocks/src/controls/Boolean.stories.tsx
@@ -15,7 +15,6 @@ const meta = {
     info: 'This is info for the Boolean control stories',
     jsx: { useBooleanShorthandSyntax: false },
   },
-  args: { name: 'boolean' },
 } as Meta;
 
 export default meta;
@@ -23,25 +22,29 @@ export default meta;
 export const True: StoryObj = {
   args: {
     value: true,
+    name: 'True',
   },
 };
 export const False: StoryObj = {
   args: {
     value: false,
+    name: 'False',
   },
 };
 
 export const Undefined: StoryObj = {
   args: {
     value: undefined,
+    name: 'Undefined',
   },
 };
 
 export const Toggling: StoryObj = {
   args: {
     value: undefined,
+    name: 'Toggling',
   },
-  play: async ({ canvasElement, id }) => {
+  play: async ({ canvasElement, id, name, ...props }) => {
     const channel = addons.getChannel();
 
     channel.emit(RESET_STORY_ARGS, { storyId: id });
@@ -55,23 +58,26 @@ export const Toggling: StoryObj = {
     const setBooleanControl = canvas.getByText('Set boolean');
     await fireEvent.click(setBooleanControl);
 
-    let toggle = await canvas.findByTitle('Change to true');
-    expect(toggle).toBeInTheDocument();
+    let toggle = await canvas.findByLabelText(name);
+    expect(toggle).toBeVisible();
 
     // from False to True
     await fireEvent.click(toggle);
-    toggle = await canvas.findByTitle('Change to false');
-    expect(toggle).toBeInTheDocument();
+    toggle = await canvas.findByRole('switch');
+    expect(toggle).not.toBeChecked();
 
     // from True to False
     await fireEvent.click(toggle);
-    toggle = await canvas.findByTitle('Change to true');
+    toggle = await canvas.findByRole('switch');
     expect(toggle).toBeInTheDocument();
   },
 };
 
 export const TogglingInDocs: StoryObj = {
   ...Toggling,
+  args: {
+    name: 'Toggling In Docs',
+  },
   parameters: {
     docs: {
       autoplay: true,
diff --git a/code/ui/blocks/src/controls/Boolean.tsx b/code/ui/blocks/src/controls/Boolean.tsx
index 9d591d1a9c75..88e8f4fc801a 100644
--- a/code/ui/blocks/src/controls/Boolean.tsx
+++ b/code/ui/blocks/src/controls/Boolean.tsx
@@ -98,7 +98,14 @@ export type BooleanProps = ControlProps & BooleanConfig;
  * 
  * ```
  */
-export const BooleanControl: FC = ({ name, value, onChange, onBlur, onFocus }) => {
+export const BooleanControl: FC = ({
+  name,
+  value,
+  onChange,
+  onBlur,
+  onFocus,
+  ...props
+}) => {
   const onSetFalse = useCallback(() => onChange(false), [onChange]);
   if (value === undefined) {
     return (
@@ -112,16 +119,17 @@ export const BooleanControl: FC = ({ name, value, onChange, onBlur
   const parsedValue = typeof value === 'string' ? parse(value) : value;
 
   return (
-