From 29f8596e326a8ae6c501e965afd4dd8f87aa3f8a Mon Sep 17 00:00:00 2001
From: Kasper Peulen <kasperpeulen@gmail.com>
Date: Thu, 17 Aug 2023 16:27:08 +0200
Subject: [PATCH 01/45] 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<Renderer> = (context) => {
     return acc;
   }, {} as Args);
 };
+
+export const attachActionsToFunctionMocks: ArgsEnhancer<Renderer> = (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<jest.Expect, keyof jest.Expect> {
+  /**
+   * 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.
+   */
+  <T = any>(actual: T): jest.JestMatchersShape<
+    jest.Matchers<Promise<void>, T>,
+    jest.Matchers<Promise<void>, 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 <kasperpeulen@gmail.com>
Date: Fri, 25 Aug 2023 16:11:48 +0200
Subject: [PATCH 02/45] 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<TObj> = {
-  [Property in keyof TObj]: TObj[Property] & { __originalFn__: PatchedObj<TObj> };
+type PatchedObj<TObj extends Record<string, unknown>> = {
+  [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<TObj extends { [x: string]: any }>(obj: TObj, options: Options): PatchedObj<TObj> {
-    if (!isInstrumentable(obj)) return obj;
+  instrument<TObj extends Record<string, unknown>>(obj: TObj, options: Options): PatchedObj<TObj> {
+    if (!isInstrumentable(obj)) return obj as PatchedObj<TObj>;
 
     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<string, any>)[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<string, unknown>,
+    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<string, unknown>, 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<string, unknown>, 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<string | CallRef>;
   getArgs?: (call: Call, state: State) => Call['args'];
+  getKeys?: (originalObject: Record<string, unknown>) => 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<O> = {
+  [K in keyof O]: O[K] extends (...args: infer A) => infer R
+    ? O extends R
+      ? Promisify<O[K]>
+      : (...args: A) => Promise<R>
+    : O[K];
+};
+
+// We only expose the jest compatible API for now
+export interface Assertion<T> extends Promisify<JestAssertion<T>> {
+  toHaveBeenCalledOnce(): Promise<void>;
+  toSatisfy<E>(matcher: (value: E) => boolean, message?: string): Promise<void>;
+  resolves: Promisify<Assertion<T>>;
+  rejects: Promisify<Assertion<T>>;
+}
+
+export interface Expect extends AsymmetricMatchersContaining {
+  <T>(actual: T, message?: string): Assertion<T>;
+  unreachable(message?: string): Promise<never>;
+  soft<T>(actual: T, message?: string): Assertion<T>;
+  extend(expects: MatchersObject): void;
+  assertions(expected: number): Promise<void>;
+  hasAssertions(): Promise<void>;
+  anything(): any;
+  any(constructor: unknown): any;
+  getState(): MatcherState;
+  setState(state: Partial<MatcherState>): 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<MatcherState>(expect);
+  expect.setState = (state) => setState(state as Partial<MatcherState>, 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<MatcherState>(
+    {
+      // 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<jest.Expect, keyof jest.Expect> {
-  /**
-   * 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.
-   */
-  <T = any>(actual: T): jest.JestMatchersShape<
-    jest.Matchers<Promise<void>, T>,
-    jest.Matchers<Promise<void>, 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 <kasperpeulen@gmail.com>
Date: Fri, 25 Aug 2023 16:48:20 +0200
Subject: [PATCH 03/45] 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<string, unknown>) => {
       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 <kasperpeulen@gmail.com>
Date: Tue, 19 Sep 2023 09:20:15 +0200
Subject: [PATCH 04/45] 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<O> = {
-  [K in keyof O]: O[K] extends (...args: infer A) => infer R
-    ? O extends R
-      ? Promisify<O[K]>
-      : (...args: A) => Promise<R>
-    : O[K];
-};
+import type { PromisifyObject } from './utils';
 
 // We only expose the jest compatible API for now
-export interface Assertion<T> extends Promisify<JestAssertion<T>> {
+export interface Assertion<T> extends PromisifyObject<JestAssertion<T>> {
   toHaveBeenCalledOnce(): Promise<void>;
   toSatisfy<E>(matcher: (value: E) => boolean, message?: string): Promise<void>;
-  resolves: Promisify<Assertion<T>>;
-  rejects: Promisify<Assertion<T>>;
+  resolves: Assertion<T>;
+  rejects: Assertion<T>;
+  not: Assertion<T>;
 }
 
 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<Omit<TestingLibraryDom, 'fireEvent' | 'within'>> & {
+  fireEvent: Promisify<FireFunction> & PromisifyObject<FireObject>;
+  within: (
+    element: HTMLElement
+  ) => PromisifyObject<BoundFunctions<typeof domTestingLibrary.queries>>;
+};
+
+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> = Fn extends (...args: infer A) => infer R
+  ? (...args: A) => R extends Promise<any> ? R : Promise<R>
+  : Fn;
+
+export type PromisifyObject<O> = { -readonly [K in keyof O]: Promisify<O[K]> };
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 <kasperpeulen@gmail.com>
Date: Tue, 19 Sep 2023 11:28:24 +0200
Subject: [PATCH 05/45] 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<T> extends PromisifyObject<JestAssertion<T>> {
+export interface Assertion<T>
+  extends PromisifyObject<JestAssertion<T>>,
+    TestingLibraryMatchers<ReturnType<ExpectStatic['stringContaining']>, Promise<void>> {
   toHaveBeenCalledOnce(): Promise<void>;
   toSatisfy<E>(matcher: (value: E) => boolean, message?: string): Promise<void>;
   resolves: Assertion<T>;
@@ -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 <kasperpeulen@gmail.com>
Date: Wed, 20 Sep 2023 14:09:29 +0200
Subject: [PATCH 06/45] 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 <kasperpeulen@gmail.com>
Date: Wed, 20 Sep 2023 15:02:35 +0200
Subject: [PATCH 07/45] 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 <kasperpeulen@gmail.com>
Date: Wed, 20 Sep 2023 15:46:53 +0200
Subject: [PATCH 08/45] 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<Renderer> = ({ 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 <kasperpeulen@gmail.com>
Date: Wed, 20 Sep 2023 16:56:25 +0200
Subject: [PATCH 09/45] 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<Renderer> = (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<Options> & Partial<TelejsonOptions>;
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<Renderer>)
+          : 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 */
 /// <reference types="node" />
 
 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 <kasperpeulen@gmail.com>
Date: Thu, 21 Sep 2023 16:49:59 +0200
Subject: [PATCH 10/45] 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<TObj extends Record<string, unknown>>(obj: TObj, options: Options): PatchedObj<TObj> {
+  instrument<TObj extends Record<string, unknown>>(
+    obj: TObj,
+    options: Options,
+    depth = 0
+  ): PatchedObj<TObj> {
     if (!isInstrumentable(obj)) return obj as PatchedObj<TObj>;
 
     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<string, any>)[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<TObj extends Record<string, any>>(
     return obj;
   }
 }
+
+function getPropertyDescriptor<T>(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<string | CallRef>;
   getArgs?: (call: Call, state: State) => Call['args'];
-  getKeys?: (originalObject: Record<string, unknown>) => string[];
+  getKeys?: (originalObject: Record<string, unknown>, 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<string, unknown>) => {
+    getKeys: (obj: Record<string, unknown>, 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<Omit<TestingLibraryDom, 'fireEvent' | 'within'>> & {
+) as {} as PromisifyObject<Omit<TestingLibraryDom, 'fireEvent'>> & {
   fireEvent: Promisify<FireFunction> & PromisifyObject<FireObject>;
-  within: (
-    element: HTMLElement
-  ) => PromisifyObject<BoundFunctions<typeof domTestingLibrary.queries>>;
 };
 
 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 <yannbf@gmail.com>
Date: Thu, 21 Sep 2023 14:57:17 +0200
Subject: [PATCH 11/45] 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 <kasperpeulen@gmail.com>
Date: Thu, 21 Sep 2023 17:14:38 +0200
Subject: [PATCH 12/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 09:20:49 +0200
Subject: [PATCH 13/45] 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<Renderer>)
-          : 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<Renderer>)
+    //       : 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 09:37:33 +0200
Subject: [PATCH 14/45] 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<Omit<TestingLibraryDom, 'fireEvent'>> & {
+) as {} as Writable<Omit<TestingLibraryDom, 'fireEvent'>> & {
   fireEvent: Promisify<FireFunction> & PromisifyObject<FireObject>;
 };
 
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> = Fn extends (...args: infer A) => infer R
   ? (...args: A) => R extends Promise<any> ? R : Promise<R>
   : Fn;
 
-export type PromisifyObject<O> = { -readonly [K in keyof O]: Promisify<O[K]> };
+export type PromisifyObject<O> = { [K in keyof O]: Promisify<O[K]> };
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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 12:00:50 +0200
Subject: [PATCH 15/45] 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<string, any>)[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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 12:04:05 +0200
Subject: [PATCH 16/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 12:26:39 +0200
Subject: [PATCH 17/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 16:45:54 +0200
Subject: [PATCH 18/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 16:55:58 +0200
Subject: [PATCH 19/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 20:42:39 +0200
Subject: [PATCH 20/45] 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 <kasperpeulen@gmail.com>
Date: Fri, 22 Sep 2023 20:49:47 +0200
Subject: [PATCH 21/45] 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 <kasperpeulen@gmail.com>
Date: Sat, 23 Sep 2023 15:43:01 +0200
Subject: [PATCH 22/45] 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<string, any>)[key],
+                { ...options, path: path.concat(key) },
+                depth
+              );
+            },
+          });
+          return acc;
+        }
+
         const value = (obj as Record<string, any>)[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 <kasperpeulen@gmail.com>
Date: Sat, 23 Sep 2023 15:51:07 +0200
Subject: [PATCH 23/45] 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 <kasperpeulen@gmail.com>
Date: Tue, 3 Oct 2023 11:36:26 +0200
Subject: [PATCH 24/45] 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<string, any>)[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 <kasperpeulen@gmail.com>
Date: Wed, 4 Oct 2023 12:38:14 +0200
Subject: [PATCH 25/45] 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 <kasperpeulen@gmail.com>
Date: Tue, 3 Oct 2023 15:17:26 +0200
Subject: [PATCH 26/45] 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 <kasperpeulen@gmail.com>
Date: Wed, 4 Oct 2023 13:48:55 +0200
Subject: [PATCH 27/45] 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<string, unknown>, 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 <kasperpeulen@gmail.com>
Date: Wed, 4 Oct 2023 13:52:22 +0200
Subject: [PATCH 28/45] 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 <kasperpeulen@gmail.com>
Date: Thu, 5 Oct 2023 15:40:55 +0200
Subject: [PATCH 29/45] 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 <kasperpeulen@gmail.com>
Date: Thu, 5 Oct 2023 15:45:56 +0200
Subject: [PATCH 30/45] 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 @@
 /// <reference types="@types/jest" />;
-/// <reference types="@testing-library/jest-dom" />;
 import React from 'react';
 import type { Meta, StoryObj } from '@storybook/react';
 import { userEvent, within } from '@storybook/testing-library';

From fb8461369a7ad77d9c27acb301bde53db4475ba6 Mon Sep 17 00:00:00 2001
From: Kasper Peulen <kasperpeulen@gmail.com>
Date: Tue, 10 Oct 2023 10:18:18 +0200
Subject: [PATCH 31/45] 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 (
     <RowMessage>
       <pre>{paragraphs[0]}</pre>
+
+      {exception.showDiff && exception.diff ? (
+        <>
+          <br />
+          <MatcherResult message={exception.diff} style={{ padding: 0 }} />
+        </>
+      ) : (
+        <pre>
+          <br />
+          {exception.expected && (
+            <>
+              Expected: <Expected value={exception.expected} />
+              <br />
+            </>
+          )}
+          {exception.actual && (
+            <>
+              Received: <Received value={exception.actual} />
+              <br />
+            </>
+          )}
+        </pre>
+      )}
       {more && <p>See the full stack trace in the browser console.</p>}
     </RowMessage>
   );
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 <StyledExpected>{value}</StyledExpected>;
 };
 
-export const MatcherResult = ({ message }: { message: string }) => {
+export const MatcherResult = ({
+  message,
+  style = {},
+}: {
+  message: string;
+  style?: React.CSSProperties;
+}) => {
   const lines = message.split('\n');
   return (
     <pre
@@ -53,6 +59,7 @@ export const MatcherResult = ({ message }: { message: string }) => {
         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 <kasperpeulen@gmail.com>
Date: Tue, 10 Oct 2023 11:58:55 +0200
Subject: [PATCH 32/45] 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 <kasperpeulen@gmail.com>
Date: Tue, 10 Oct 2023 15:50:27 +0200
Subject: [PATCH 33/45] 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<Meta<TestButtonProps>>();
 });
+
+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<typeof TestButton>;
+
+  type Story = StoryObj<typeof meta>;
+
+  const Basic: Story = {
+    play: async ({ args }) => {
+      expectTypeOf(args.onClick).toEqualTypeOf<Mock<[], void>>();
+      expectTypeOf(args.onRender).toEqualTypeOf<() => JSX.Element>();
+    },
+  };
+  type Expected = StoryAnnotations<
+    ReactRenderer,
+    Props & { onClick: Mock<[], void> },
+    Partial<Props>
+  >;
+
+  expectTypeOf(Basic).toEqualTypeOf<Expected>();
+});
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 = Args> = [TMetaOrCmpOrArgs] extends [
     > extends infer TArgs
     ? StoryAnnotations<
         ReactRenderer,
-        TArgs,
+        AddMocks<TArgs, DefaultArgs>,
         SetOptional<TArgs, keyof TArgs & keyof (DefaultArgs & ActionArgs<TArgs>)>
       >
     : never
@@ -64,6 +64,16 @@ export type StoryObj<TMetaOrCmpOrArgs = Args> = [TMetaOrCmpOrArgs] extends [
   ? StoryAnnotations<ReactRenderer, ComponentProps<TMetaOrCmpOrArgs>>
   : StoryAnnotations<ReactRenderer, TMetaOrCmpOrArgs>;
 
+// This performs a downcast to function types that are mocks, when a mock fn is given to meta args.
+type AddMocks<TArgs, DefaultArgs> = 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<TArgs> = {
   // 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 c80c4a2be8d1b6c6c19f6c299724568b1e0be7cc Mon Sep 17 00:00:00 2001
From: Mark berry <markberry867@gmail.com>
Date: Sun, 15 Oct 2023 04:03:37 -0500
Subject: [PATCH 34/45] Avoid CSP issue in A11y

---
 code/addons/a11y/src/a11yRunner.ts | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/code/addons/a11y/src/a11yRunner.ts b/code/addons/a11y/src/a11yRunner.ts
index 4163017fd7f9..fb32e0f543a0 100644
--- a/code/addons/a11y/src/a11yRunner.ts
+++ b/code/addons/a11y/src/a11yRunner.ts
@@ -45,12 +45,18 @@ const run = async (storyId: string) => {
       }
 
       const result = await axe.run(htmlElement, options);
+
+      // Axe result contains class instances, which telejson deserializes in a
+      // way that violates:
+      //  Content Security Policy directive: "script-src 'self' 'unsafe-inline'".
+      const resultJson = JSON.parse(JSON.stringify(result));
+
       // It's possible that we requested a new run on a different story.
       // Unfortunately, axe doesn't support a cancel method to abort current run.
       // We check if the story we run against is still the current one,
       // if not, trigger a new run using the current story
       if (activeStoryId === storyId) {
-        channel.emit(EVENTS.RESULT, result);
+        channel.emit(EVENTS.RESULT, resultJson);
       } else {
         active = false;
         run(activeStoryId);

From cca1bad2a2cd34f0c471871540cb94b4df5722a0 Mon Sep 17 00:00:00 2001
From: jonniebigodes <joaocontadesenvolvimento@gmail.com>
Date: Thu, 19 Oct 2023 19:13:29 +0100
Subject: [PATCH 35/45] Docs: Vite builder updates

---
 docs/api/main-config-vite-final.md            |  2 +-
 docs/builders/vite.md                         | 26 ++++++++++++++----
 .../main-config-builder-custom-config.js.mdx  | 15 +++++++++++
 .../main-config-core-builder.ts-4-9.mdx       | 21 +++++++++++++++
 .../common/main-config-vite-final-env.js.mdx  | 23 ++++++++++++++++
 .../common/main-config-vite-final.ts-4-9.mdx  | 27 +++++++++++++++++++
 ...storybook-vite-builder-react-docgen.js.mdx |  2 +-
 ...ybook-vite-builder-ts-configure.ts-4-9.mdx | 17 ++++++++++++
 8 files changed, 126 insertions(+), 7 deletions(-)
 create mode 100644 docs/snippets/common/main-config-builder-custom-config.js.mdx
 create mode 100644 docs/snippets/common/main-config-core-builder.ts-4-9.mdx
 create mode 100644 docs/snippets/common/main-config-vite-final-env.js.mdx
 create mode 100644 docs/snippets/common/main-config-vite-final.ts-4-9.mdx
 create mode 100644 docs/snippets/common/storybook-vite-builder-ts-configure.ts-4-9.mdx

diff --git a/docs/api/main-config-vite-final.md b/docs/api/main-config-vite-final.md
index c21ba01da4b0..02073acee85f 100644
--- a/docs/api/main-config-vite-final.md
+++ b/docs/api/main-config-vite-final.md
@@ -6,7 +6,7 @@ Parent: [main.js|ts configuration](./main-config.md)
 
 Type: `(config: Vite.InlineConfig, options: Options) => Vite.InlineConfig | Promise<Vite.InlineConfig>`
 
-Customize Storybook's Vite setup when using the [vite builder](../builders/vite.md).
+Customize Storybook's Vite setup when using the [Vite builder](../builders/vite.md).
 
 <!-- prettier-ignore-start -->
 
diff --git a/docs/builders/vite.md b/docs/builders/vite.md
index d964931f66ab..b7a9ff7e7cdf 100644
--- a/docs/builders/vite.md
+++ b/docs/builders/vite.md
@@ -39,9 +39,9 @@ Update your Storybook configuration (in `.storybook/main.js|ts`) to include the
 
 ## Configuration
 
-Out of the box, Storybook's Vite builder includes a set of configuration defaults for the supported frameworks, which are merged alongside your existing configuration file. For an optimal experience when using the Vite builder, we recommend applying any configuration directly inside Vite's configuration file (i.e., [`vite.config.js`](https://vitejs.dev/config/)).
+Out of the box, Storybook's Vite builder includes a set of configuration defaults for the supported frameworks, which are merged alongside your existing configuration file. For an optimal experience when using the Vite builder, we recommend applying any configuration directly inside Vite's configuration file (i.e., [`vite.config.js|ts`](https://vitejs.dev/config/)).
 
-When Storybook loads, it automatically merges the configuration into its own. However, not all projects have the same requirements, and you may need to provide a custom configuration created specifically for Storybook. In that case, you can adjust your configuration file (.storybook/main.js|ts) and add the `viteFinal` configuration function as follows:
+When Storybook loads, it automatically merges the configuration into its own. However, since different projects may have specific requirements, you may need to provide a custom configuration for Storybook. In such cases, you can modify your configuration file (`.storybook/main.js|ts`) and add the `viteFinal` configuration function as follows:
 
 <!-- prettier-ignore-start -->
 
@@ -53,15 +53,31 @@ When Storybook loads, it automatically merges the configuration into its own. Ho
 
 <!-- prettier-ignore-end -->
 
-The asynchronous function `viteFinal` receives a `config` object with the default builder configuration and returns the updated configuration.
+The asynchronous function [`viteFinal`](../api/main-config-vite-final.md) receives a `config` object with the default builder configuration and returns the updated configuration.
 
-You can also override the builder's configuration based on the environment. For instance, if you need to provide a custom configuration for development purposes and another for production, you can extend the default configuration as follows:
+### Environment-based configuration
+
+If you need to customize the builder's configuration and apply specific options based on your environment, extend the `viteFinal` function as follows:
+
+<!-- prettier-ignore-start -->
+
+<CodeSnippets
+  paths={[
+    'common/main-config-vite-final-env.js.mdx'
+  ]}
+/>
+
+<!-- prettier-ignore-end -->
+
+### Override the default configuration
+
+By default, the Vite builder in Storybook searches for the Vite configuration file in the root directory of your Storybook project. However, you can customize it to look for the configuration file in a different location. For example:
 
 <!-- prettier-ignore-start -->
 
 <CodeSnippets
   paths={[
-    'common/main-config-vite-final.js.mdx',
+    'common/main-config-builder-custom-config.js.mdx',
   ]}
 />
 
diff --git a/docs/snippets/common/main-config-builder-custom-config.js.mdx b/docs/snippets/common/main-config-builder-custom-config.js.mdx
new file mode 100644
index 000000000000..032d8ea6334b
--- /dev/null
+++ b/docs/snippets/common/main-config-builder-custom-config.js.mdx
@@ -0,0 +1,15 @@
+```js
+// .storybook/main.js|ts
+
+export default {
+  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+  core: {
+    builder: {
+      name: '@storybook/builder-vite',
+      options: {
+        viteConfigPath: '../customVite.config.js',
+      },
+    },
+  },
+};
+```
diff --git a/docs/snippets/common/main-config-core-builder.ts-4-9.mdx b/docs/snippets/common/main-config-core-builder.ts-4-9.mdx
new file mode 100644
index 000000000000..e28b069e3f12
--- /dev/null
+++ b/docs/snippets/common/main-config-core-builder.ts-4-9.mdx
@@ -0,0 +1,21 @@
+```ts
+// .storybook/main.ts
+
+// Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
+import type { StorybookConfig } from '@storybook/your-framework';
+
+const config: StorybookConfig = {
+  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+  framework: '@storybook/your-framework',
+  core: {
+    builder: {
+      name: '@storybook/builder-vite',
+      options: {
+        viteConfigPath: '../../../vite.config.js',
+      },
+    },
+  },
+};
+
+export default config;
+```
diff --git a/docs/snippets/common/main-config-vite-final-env.js.mdx b/docs/snippets/common/main-config-vite-final-env.js.mdx
new file mode 100644
index 000000000000..73926f408471
--- /dev/null
+++ b/docs/snippets/common/main-config-vite-final-env.js.mdx
@@ -0,0 +1,23 @@
+```js
+// .storybook/main.js|ts
+
+import { mergeConfig } from 'vite';
+
+export default {
+  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+  core: {
+    builder: '@storybook/builder-vite',
+  },
+  async viteFinal(config, { configType }) {
+    if (configType === 'DEVELOPMENT') {
+      // Your development configuration goes here
+    }
+    if (configType === 'PRODUCTION') {
+      // Your production configuration goes here.
+    }
+    return mergeConfig(config, {
+      // Your environment configuration here
+    });
+  },
+};
+```
diff --git a/docs/snippets/common/main-config-vite-final.ts-4-9.mdx b/docs/snippets/common/main-config-vite-final.ts-4-9.mdx
new file mode 100644
index 000000000000..42d7f8cf8b9d
--- /dev/null
+++ b/docs/snippets/common/main-config-vite-final.ts-4-9.mdx
@@ -0,0 +1,27 @@
+```ts
+// .storybook/main.ts
+
+// Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite)
+import type { StorybookConfig } from '@storybook/your-framework';
+
+import { mergeConfig } from 'vite';
+
+const config: StorybookConfig = {
+  // Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite)
+  framework: '@storybook/your-framework',
+  stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+  async viteFinal(config, { configType }) {
+    if (configType === 'DEVELOPMENT') {
+      // Your development configuration goes here
+    }
+    if (configType === 'PRODUCTION') {
+      // Your production configuration goes here.
+    }
+    return mergeConfig(config, {
+      // Your environment configuration here
+    });
+  },
+};
+
+export default config;
+```
diff --git a/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx b/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx
index 63dcbfaea126..99ef2c6a0372 100644
--- a/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx
+++ b/docs/snippets/common/storybook-vite-builder-react-docgen.js.mdx
@@ -1,5 +1,5 @@
 ```js
-// .storybook/main.js
+// .storybook/main.js|ts
 
 export default {
   stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
diff --git a/docs/snippets/common/storybook-vite-builder-ts-configure.ts-4-9.mdx b/docs/snippets/common/storybook-vite-builder-ts-configure.ts-4-9.mdx
new file mode 100644
index 000000000000..397e526c0b0a
--- /dev/null
+++ b/docs/snippets/common/storybook-vite-builder-ts-configure.ts-4-9.mdx
@@ -0,0 +1,17 @@
+```ts
+// .storybook/main.ts
+
+// Replace your-framework with the framework you are using (e.g., react-vite, vue3-vite)
+import type { StorybookConfig } from '@storybook/your-framework';
+
+const config: StorybookConfig = {
+  framework: '@storybook/your-framework',
+  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
+  async viteFinal(config, options) {
+    // Add your configuration here
+    return config;
+  },
+};
+
+export default config;
+```

From f42e9efbba01ab40c5cdd770e6fc96aaf6ed189a Mon Sep 17 00:00:00 2001
From: Kasper Peulen <kasperpeulen@gmail.com>
Date: Wed, 25 Oct 2023 15:09:48 +0200
Subject: [PATCH 36/45] Pre bundle most deps of the test package

---
 code/lib/test/package.json | 9 +++++++--
 code/yarn.lock             | 3 +--
 scripts/prepare/bundle.ts  | 4 +++-
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/code/lib/test/package.json b/code/lib/test/package.json
index 7de3167917c8..73b04a6e593f 100644
--- a/code/lib/test/package.json
+++ b/code/lib/test/package.json
@@ -54,11 +54,10 @@
     "@vitest/expect": "^0.34.2",
     "@vitest/spy": "^0.34.1",
     "chai": "^4.3.7",
-    "expect": "^29.6.2",
-    "ts-dedent": "^2.2.0",
     "util": "^0.12.4"
   },
   "devDependencies": {
+    "ts-dedent": "^2.2.0",
     "type-fest": "~2.19",
     "typescript": "~4.9.3"
   },
@@ -68,6 +67,12 @@
   "bundler": {
     "entries": [
       "./src/index.ts"
+    ],
+    "noExternal": [
+      "@testing-library/dom",
+      "@testing-library/jest-dom",
+      "@testing-library/user-event",
+      "chai"
     ]
   },
   "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae17"
diff --git a/code/yarn.lock b/code/yarn.lock
index 35eb213e84d6..778da8443e19 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -8166,7 +8166,6 @@ __metadata:
     "@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
@@ -16910,7 +16909,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"expect@npm:^29.0.0, expect@npm:^29.6.2, expect@npm:^29.7.0":
+"expect@npm:^29.0.0, expect@npm:^29.7.0":
   version: 29.7.0
   resolution: "expect@npm:29.7.0"
   dependencies:
diff --git a/scripts/prepare/bundle.ts b/scripts/prepare/bundle.ts
index 02199ecff992..1228e445a034 100755
--- a/scripts/prepare/bundle.ts
+++ b/scripts/prepare/bundle.ts
@@ -16,6 +16,7 @@ type Formats = 'esm' | 'cjs';
 type BundlerConfig = {
   entries: string[];
   externals: string[];
+  noExternal: string[];
   platform: Options['platform'];
   pre: string;
   post: string;
@@ -36,6 +37,7 @@ const run = async ({ cwd, flags }: { cwd: string; flags: string[] }) => {
     bundler: {
       entries = [],
       externals: extraExternals = [],
+      noExternal: extraNoExternal = [],
       platform,
       pre,
       post,
@@ -79,7 +81,7 @@ const run = async ({ cwd, flags }: { cwd: string; flags: string[] }) => {
    */
   const nonPresetEntries = allEntries.filter((f) => !path.parse(f).name.includes('preset'));
 
-  const noExternal = [/^@vitest\/.+$/];
+  const noExternal = [/^@vitest\/.+$/, ...extraNoExternal];
 
   if (formats.includes('esm')) {
     tasks.push(

From 3fa771c2f0f4a0abfab61e3d3353e443d7af6759 Mon Sep 17 00:00:00 2001
From: nikospapcom <admin@nikospap.com>
Date: Fri, 27 Oct 2023 10:42:35 +0300
Subject: [PATCH 37/45] feat: Support next@14.0.0

---
 code/frameworks/nextjs/package.json |  6 +-
 code/yarn.lock                      | 96 ++++++++++++++---------------
 node_modules/.package-lock.json     |  6 ++
 3 files changed, 57 insertions(+), 51 deletions(-)
 create mode 100644 node_modules/.package-lock.json

diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 76fdfcd405e1..0be65ee2da6d 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -119,13 +119,13 @@
     "@types/babel__core": "^7",
     "@types/babel__plugin-transform-runtime": "^7",
     "@types/babel__preset-env": "^7",
-    "next": "13.5.4",
+    "next": "14.0.0",
     "typescript": "^4.9.3",
     "webpack": "^5.65.0"
   },
   "peerDependencies": {
     "@next/font": "^13.0.0",
-    "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
+    "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
     "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
     "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
     "webpack": "^5.0.0"
@@ -145,7 +145,7 @@
     }
   },
   "engines": {
-    "node": ">=16.0.0"
+    "node": ">=18.17.0"
   },
   "publishConfig": {
     "access": "public"
diff --git a/code/yarn.lock b/code/yarn.lock
index ac5d3a3cadb9..2e85205f3e12 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -3973,72 +3973,72 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@next/env@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/env@npm:13.5.4"
-  checksum: 69c013047371bde6c4dc6d03ec77140059bd4e3db38c1991a8aa8a9c8ce4d1370b98a141145a6f60e23f32ce97a3040b448bfd0455b0d9e5ba6efda8df33c89f
+"@next/env@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/env@npm:14.0.0"
+  checksum: c43e81dbd162a29a4b380342e416209d69d731e8ced7688d09668ec8196f543e358ed65adad81a26e943c63a293d7a018552f8389b6b1ac95cd0f63f4ef257c0
   languageName: node
   linkType: hard
 
-"@next/swc-darwin-arm64@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-darwin-arm64@npm:13.5.4"
+"@next/swc-darwin-arm64@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-darwin-arm64@npm:14.0.0"
   conditions: os=darwin & cpu=arm64
   languageName: node
   linkType: hard
 
-"@next/swc-darwin-x64@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-darwin-x64@npm:13.5.4"
+"@next/swc-darwin-x64@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-darwin-x64@npm:14.0.0"
   conditions: os=darwin & cpu=x64
   languageName: node
   linkType: hard
 
-"@next/swc-linux-arm64-gnu@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-linux-arm64-gnu@npm:13.5.4"
+"@next/swc-linux-arm64-gnu@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-linux-arm64-gnu@npm:14.0.0"
   conditions: os=linux & cpu=arm64 & libc=glibc
   languageName: node
   linkType: hard
 
-"@next/swc-linux-arm64-musl@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-linux-arm64-musl@npm:13.5.4"
+"@next/swc-linux-arm64-musl@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-linux-arm64-musl@npm:14.0.0"
   conditions: os=linux & cpu=arm64 & libc=musl
   languageName: node
   linkType: hard
 
-"@next/swc-linux-x64-gnu@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-linux-x64-gnu@npm:13.5.4"
+"@next/swc-linux-x64-gnu@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-linux-x64-gnu@npm:14.0.0"
   conditions: os=linux & cpu=x64 & libc=glibc
   languageName: node
   linkType: hard
 
-"@next/swc-linux-x64-musl@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-linux-x64-musl@npm:13.5.4"
+"@next/swc-linux-x64-musl@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-linux-x64-musl@npm:14.0.0"
   conditions: os=linux & cpu=x64 & libc=musl
   languageName: node
   linkType: hard
 
-"@next/swc-win32-arm64-msvc@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-win32-arm64-msvc@npm:13.5.4"
+"@next/swc-win32-arm64-msvc@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-win32-arm64-msvc@npm:14.0.0"
   conditions: os=win32 & cpu=arm64
   languageName: node
   linkType: hard
 
-"@next/swc-win32-ia32-msvc@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-win32-ia32-msvc@npm:13.5.4"
+"@next/swc-win32-ia32-msvc@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-win32-ia32-msvc@npm:14.0.0"
   conditions: os=win32 & cpu=ia32
   languageName: node
   linkType: hard
 
-"@next/swc-win32-x64-msvc@npm:13.5.4":
-  version: 13.5.4
-  resolution: "@next/swc-win32-x64-msvc@npm:13.5.4"
+"@next/swc-win32-x64-msvc@npm:14.0.0":
+  version: 14.0.0
+  resolution: "@next/swc-win32-x64-msvc@npm:14.0.0"
   conditions: os=win32 & cpu=x64
   languageName: node
   linkType: hard
@@ -7323,7 +7323,7 @@ __metadata:
     fs-extra: "npm:^11.1.0"
     image-size: "npm:^1.0.0"
     loader-utils: "npm:^3.2.0"
-    next: "npm:13.5.4"
+    next: "npm:14.0.0"
     node-polyfill-webpack-plugin: "npm:^2.0.1"
     pnp-webpack-plugin: "npm:^1.7.0"
     postcss: "npm:^8.4.21"
@@ -7340,7 +7340,7 @@ __metadata:
     webpack: "npm:^5.65.0"
   peerDependencies:
     "@next/font": ^13.0.0
-    next: ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0
+    next: ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0
     react: ^16.8.0 || ^17.0.0 || ^18.0.0
     react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
     webpack: ^5.0.0
@@ -23937,20 +23937,20 @@ __metadata:
   languageName: node
   linkType: hard
 
-"next@npm:13.5.4":
-  version: 13.5.4
-  resolution: "next@npm:13.5.4"
-  dependencies:
-    "@next/env": "npm:13.5.4"
-    "@next/swc-darwin-arm64": "npm:13.5.4"
-    "@next/swc-darwin-x64": "npm:13.5.4"
-    "@next/swc-linux-arm64-gnu": "npm:13.5.4"
-    "@next/swc-linux-arm64-musl": "npm:13.5.4"
-    "@next/swc-linux-x64-gnu": "npm:13.5.4"
-    "@next/swc-linux-x64-musl": "npm:13.5.4"
-    "@next/swc-win32-arm64-msvc": "npm:13.5.4"
-    "@next/swc-win32-ia32-msvc": "npm:13.5.4"
-    "@next/swc-win32-x64-msvc": "npm:13.5.4"
+"next@npm:14.0.0":
+  version: 14.0.0
+  resolution: "next@npm:14.0.0"
+  dependencies:
+    "@next/env": "npm:14.0.0"
+    "@next/swc-darwin-arm64": "npm:14.0.0"
+    "@next/swc-darwin-x64": "npm:14.0.0"
+    "@next/swc-linux-arm64-gnu": "npm:14.0.0"
+    "@next/swc-linux-arm64-musl": "npm:14.0.0"
+    "@next/swc-linux-x64-gnu": "npm:14.0.0"
+    "@next/swc-linux-x64-musl": "npm:14.0.0"
+    "@next/swc-win32-arm64-msvc": "npm:14.0.0"
+    "@next/swc-win32-ia32-msvc": "npm:14.0.0"
+    "@next/swc-win32-x64-msvc": "npm:14.0.0"
     "@swc/helpers": "npm:0.5.2"
     busboy: "npm:1.6.0"
     caniuse-lite: "npm:^1.0.30001406"
@@ -23988,7 +23988,7 @@ __metadata:
       optional: true
   bin:
     next: dist/bin/next
-  checksum: 0b0bc7fa42844859a0444a79122a48b5e65116c30ce077a3edaaecd7cee1d7925214a659391ae6ecf8dc612869a7a646ab3a1a8aa12d074ff17e3f18c53a2621
+  checksum: cfb18a72d6e1d875efb1bb3806f9a06551f482c5cb87231e77e179a71d26f3d43700290988ad27e739302bfa7ff8ac8081aafd5456c39a2819fdd315617e5acf
   languageName: node
   linkType: hard
 
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 000000000000..b157d40c0f7a
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,6 @@
+{
+  "name": "@storybook/root",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {}
+}

From 83f4ef010ce052b1d7599cc42db7b980ac65dab0 Mon Sep 17 00:00:00 2001
From: nikospapcom <admin@nikospap.com>
Date: Fri, 27 Oct 2023 10:50:53 +0300
Subject: [PATCH 38/45] chore: Remove package-lock file

---
 node_modules/.package-lock.json | 6 ------
 1 file changed, 6 deletions(-)
 delete mode 100644 node_modules/.package-lock.json

diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
deleted file mode 100644
index b157d40c0f7a..000000000000
--- a/node_modules/.package-lock.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "name": "@storybook/root",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {}
-}

From a27e78999178fae5c6558a2cb6548edd32e286b5 Mon Sep 17 00:00:00 2001
From: nikospapcom <admin@nikospap.com>
Date: Fri, 27 Oct 2023 11:34:01 +0300
Subject: [PATCH 39/45] chore: Revert node engine to 16

---
 code/frameworks/nextjs/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 0be65ee2da6d..c4d58b73f0f1 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -145,7 +145,7 @@
     }
   },
   "engines": {
-    "node": ">=18.17.0"
+    "node": ">=16.0.0"
   },
   "publishConfig": {
     "access": "public"

From bcf87ea500868f6702c7ae4723adcb51693a44c0 Mon Sep 17 00:00:00 2001
From: Kasper Peulen <kasperpeulen@gmail.com>
Date: Fri, 27 Oct 2023 10:45:33 +0200
Subject: [PATCH 40/45] Fix eslint

---
 code/addons/interactions/src/preview.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/code/addons/interactions/src/preview.ts b/code/addons/interactions/src/preview.ts
index cee79b7a2dd9..54c7c18faab5 100644
--- a/code/addons/interactions/src/preview.ts
+++ b/code/addons/interactions/src/preview.ts
@@ -39,7 +39,6 @@ const addSpies = (id: string, val: any, key?: string): any => {
     if (Array.isArray(val)) {
       return val.map((item, index) => addSpies(id, item, `${key}[${index}]`));
     }
-    // eslint-disable-next-line no-underscore-dangle
     if (typeof val === 'function' && val.isAction && !val._isMockFunction) {
       Object.defineProperty(val, 'name', { value: key, writable: false });
       Object.defineProperty(val, '__storyId__', { value: id, writable: false });

From eacb4a7189b5fe4345a2637b9f80f99a4cbfe2ec Mon Sep 17 00:00:00 2001
From: jonniebigodes <joaocontadesenvolvimento@gmail.com>
Date: Fri, 27 Oct 2023 13:29:54 +0100
Subject: [PATCH 41/45] Feedback addressed

---
 docs/builders/vite.md                         | 20 +++++++++++++++++++
 .../storybook-vite-builder-jest-mock.html.mdx |  7 +++++++
 2 files changed, 27 insertions(+)
 create mode 100644 docs/snippets/common/storybook-vite-builder-jest-mock.html.mdx

diff --git a/docs/builders/vite.md b/docs/builders/vite.md
index b7a9ff7e7cdf..819c4278ed48 100644
--- a/docs/builders/vite.md
+++ b/docs/builders/vite.md
@@ -83,6 +83,12 @@ By default, the Vite builder in Storybook searches for the Vite configuration fi
 
 <!-- prettier-ignore-end -->
 
+<div class="aside">
+
+💡 If you do not want Storybook to load the Vite configuration file automatically, you can use the `viteConfigPath` option to point to a non-existent file.
+
+</div>
+
 ### TypeScript
 
 If you need, you can also configure Storybook's Vite builder using TypeScript. Rename your `.storybook/main.js` to `.storybook/main.ts` and adjust it as follows:
@@ -120,6 +126,20 @@ Currently, [automatic argType inference](../api/argtypes.md#automatic-argtype-in
 
 <!-- prettier-ignore-end -->
 
+### Interaction tests not working as expected
+
+If you are migrating from a Webpack-based project, such as [CRA](https://create-react-app.dev/), to Vite, and you have enabled Interaction testing with the [`@storybook/addon-interactions`](https://storybook.js.org/addons/@storybook/addon-interactions) addon, you may run into a situation where your tests fail to execute notifying you that the `window` object is not defined. To resolve this issue, you can create a `preview-head.html` file in your Storybook configuration directory and include the following:
+
+<!-- prettier-ignore-start -->
+
+<CodeSnippets
+  paths={[
+    'common/storybook-vite-builder-jest-mock.html.mdx',
+  ]}
+/>
+
+<!-- prettier-ignore-end -->
+
 #### Learn more about builders
 
 - Vite builder for bundling with Vite
diff --git a/docs/snippets/common/storybook-vite-builder-jest-mock.html.mdx b/docs/snippets/common/storybook-vite-builder-jest-mock.html.mdx
new file mode 100644
index 000000000000..f7dd5c715015
--- /dev/null
+++ b/docs/snippets/common/storybook-vite-builder-jest-mock.html.mdx
@@ -0,0 +1,7 @@
+```html
+<!-- .storybook/preview-head.html -->
+
+<script>
+  window.global = window;
+</script>
+```

From d888f60d660459f825aab7660f76cebd171b6f9e Mon Sep 17 00:00:00 2001
From: Kasper Peulen <kasperpeulen@gmail.com>
Date: Fri, 27 Oct 2023 14:31:47 +0200
Subject: [PATCH 42/45] Fix next version

---
 code/frameworks/nextjs/package.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index 76fdfcd405e1..e26588814fb0 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -124,8 +124,8 @@
     "webpack": "^5.65.0"
   },
   "peerDependencies": {
-    "@next/font": "^13.0.0",
-    "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
+    "@next/font": "^13.0.0 || ^14.0.0",
+    "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
     "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
     "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
     "webpack": "^5.0.0"

From 715381c08d83ad68a5fd3b3502587f29c990edfd Mon Sep 17 00:00:00 2001
From: Valentin Palkovic <valentin@chromatic.com>
Date: Fri, 27 Oct 2023 15:07:18 +0200
Subject: [PATCH 43/45] Fix next/legacy/image imports for Next.js v14

---
 code/frameworks/nextjs/package.json              |  4 ++--
 code/frameworks/nextjs/src/images/webpack.ts     |  2 +-
 code/frameworks/nextjs/src/nextImport/webpack.ts | 12 ++----------
 code/yarn.lock                                   |  6 +++---
 4 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/code/frameworks/nextjs/package.json b/code/frameworks/nextjs/package.json
index c4d58b73f0f1..d5ba68b05c9f 100644
--- a/code/frameworks/nextjs/package.json
+++ b/code/frameworks/nextjs/package.json
@@ -119,12 +119,12 @@
     "@types/babel__core": "^7",
     "@types/babel__plugin-transform-runtime": "^7",
     "@types/babel__preset-env": "^7",
-    "next": "14.0.0",
+    "next": "^14.0.0",
     "typescript": "^4.9.3",
     "webpack": "^5.65.0"
   },
   "peerDependencies": {
-    "@next/font": "^13.0.0",
+    "@next/font": "^13.0.0|| ^14.0.0",
     "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
     "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
     "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
diff --git a/code/frameworks/nextjs/src/images/webpack.ts b/code/frameworks/nextjs/src/images/webpack.ts
index e6b91f0712d3..e80e03545beb 100644
--- a/code/frameworks/nextjs/src/images/webpack.ts
+++ b/code/frameworks/nextjs/src/images/webpack.ts
@@ -20,7 +20,7 @@ const configureImageDefaults = (baseConfig: WebpackConfig): void => {
     'next/image': path.resolve(__dirname, './images/next-image'),
   };
 
-  if (semver.satisfies(version, '^13.0.0')) {
+  if (semver.satisfies(version, '>=13.0.0')) {
     resolve.alias = {
       ...resolve.alias,
       'sb-original/next/legacy/image': require.resolve('next/legacy/image'),
diff --git a/code/frameworks/nextjs/src/nextImport/webpack.ts b/code/frameworks/nextjs/src/nextImport/webpack.ts
index b017462ae256..fc5d359ef8e2 100644
--- a/code/frameworks/nextjs/src/nextImport/webpack.ts
+++ b/code/frameworks/nextjs/src/nextImport/webpack.ts
@@ -7,20 +7,11 @@ export function configureNextImport(baseConfig: WebpackConfig) {
   const nextJSVersion = getNextjsVersion();
 
   const isNext12 = semver.satisfies(nextJSVersion, '~12');
-  const isNext13 = semver.satisfies(nextJSVersion, '~13');
   const isNextVersionSmallerThan12dot2 = semver.lt(nextJSVersion, '12.2.0');
   const isNextVersionSmallerThan13 = semver.lt(nextJSVersion, '13.0.0');
 
   baseConfig.plugins = baseConfig.plugins ?? [];
 
-  if (!isNext13) {
-    baseConfig.plugins.push(
-      new IgnorePlugin({
-        resourceRegExp: /next\/legacy\/image$/,
-      })
-    );
-  }
-
   if (!isNext12 || isNextVersionSmallerThan12dot2) {
     baseConfig.plugins.push(
       new IgnorePlugin({
@@ -32,7 +23,8 @@ export function configureNextImport(baseConfig: WebpackConfig) {
   if (isNextVersionSmallerThan13) {
     baseConfig.plugins.push(
       new IgnorePlugin({
-        resourceRegExp: /next\/dist\/shared\/lib\/hooks-client-context$/,
+        // ignore next/dist/shared/lib/hooks-client-context and next/legacy/image imports
+        resourceRegExp: /(next\/dist\/shared\/lib\/hooks-client-context|next\/legacy\/image)$/,
       })
     );
   }
diff --git a/code/yarn.lock b/code/yarn.lock
index 2e85205f3e12..a4f61e11d94f 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -7323,7 +7323,7 @@ __metadata:
     fs-extra: "npm:^11.1.0"
     image-size: "npm:^1.0.0"
     loader-utils: "npm:^3.2.0"
-    next: "npm:14.0.0"
+    next: "npm:^14.0.0"
     node-polyfill-webpack-plugin: "npm:^2.0.1"
     pnp-webpack-plugin: "npm:^1.7.0"
     postcss: "npm:^8.4.21"
@@ -7339,7 +7339,7 @@ __metadata:
     typescript: "npm:^4.9.3"
     webpack: "npm:^5.65.0"
   peerDependencies:
-    "@next/font": ^13.0.0
+    "@next/font": ^13.0.0|| ^14.0.0
     next: ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0
     react: ^16.8.0 || ^17.0.0 || ^18.0.0
     react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
@@ -23937,7 +23937,7 @@ __metadata:
   languageName: node
   linkType: hard
 
-"next@npm:14.0.0":
+"next@npm:^14.0.0":
   version: 14.0.0
   resolution: "next@npm:14.0.0"
   dependencies:

From 6359db30bc160bc9949538f1d07ecfea44fc5387 Mon Sep 17 00:00:00 2001
From: jonniebigodes <joaocontadesenvolvimento@gmail.com>
Date: Fri, 27 Oct 2023 15:25:27 +0100
Subject: [PATCH 44/45] Docs: Builder Vite - Remove outdated Svelte reference

---
 code/builders/builder-vite/README.md | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/code/builders/builder-vite/README.md b/code/builders/builder-vite/README.md
index ce675ab3f580..1e5026e36443 100644
--- a/code/builders/builder-vite/README.md
+++ b/code/builders/builder-vite/README.md
@@ -9,7 +9,6 @@ Build your stories with [vite](https://vitejs.dev/) for fast startup times and n
   - [Getting started with Vite and Storybook (on a new project)](#getting-started-with-vite-and-storybook-on-a-new-project)
   - [Migration from webpack / CRA](#migration-from-webpack--cra)
   - [Customize Vite config](#customize-vite-config)
-  - [Svelte Options](#svelte-options)
   - [TypeScript](#typescript)
   - [React Docgen](#react-docgen)
   - [Note about working directory](#note-about-working-directory)
@@ -113,10 +112,6 @@ The `configType` variable will be either `"DEVELOPMENT"` or `"PRODUCTION"`.
 
 The function should return the updated Vite configuration.
 
-### Svelte Options
-
-When using this builder with Svelte, your `svelte.config.js` file will be used automatically.
-
 ### TypeScript
 
 Configure your `.storybook/main.ts` to use TypeScript:

From 1a132870b3b1022ee1f68a1beed98ce50a071b9a Mon Sep 17 00:00:00 2001
From: jonniebigodes <joaocontadesenvolvimento@gmail.com>
Date: Fri, 27 Oct 2023 16:31:27 +0100
Subject: [PATCH 45/45] Docs: Fix conditional rendering for Unit testing

---
 docs/writing-tests/stories-in-unit-tests.md | 23 +++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/docs/writing-tests/stories-in-unit-tests.md b/docs/writing-tests/stories-in-unit-tests.md
index 156294d5e480..f96a72c9fef2 100644
--- a/docs/writing-tests/stories-in-unit-tests.md
+++ b/docs/writing-tests/stories-in-unit-tests.md
@@ -172,26 +172,35 @@ If you intend to test multiple stories in a single test, use the `composeStories
 
 Storybook provides community-led addons for other frameworks like [Vue 2](https://storybook.js.org/addons/@storybook/testing-vue) and [Angular](https://storybook.js.org/addons/@storybook/testing-angular). However, these addons still lack support for the latest stable Storybook release. If you're interested in helping out, we recommend reaching out to the maintainers using the default communication channels (GitHub and [Discord server](https://discord.com/channels/486522875931656193/839297503446695956)).
 
-### The args are not being passed to the test
-
 <IfRenderer renderer='react'>
 
+### The args are not being passed to the test
+
 The components returned by `composeStories` or `composeStory` not only can be rendered as React components but also come with the combined properties from the story, meta, and global configuration. This means that if you want to access args or parameters, for instance, you can do so:
 
+<!-- prettier-ignore-start -->
+
+<CodeSnippets
+  paths={[
+    'react/reuse-args-test.js.mdx',
+    'react/reuse-args-test.ts.mdx',
+  ]}
+/>
+
+<!-- prettier-ignore-end -->
+
 </IfRenderer>
 
 <IfRenderer renderer='vue'>
 
-When using the `composeStories` or `composeStory` functions, the components being rendered will have a combination of properties from the story, meta, and global configuration. Therefore, if you need to access the args or parameters, you can do so as follows:
+### The args are not being passed to the test
 
-</IfRenderer>
+When using the `composeStories` or `composeStory` functions, the components being rendered will have a combination of properties from the story, meta, and global configuration. Therefore, if you need to access the args or parameters, you can do so as follows:
 
 <!-- prettier-ignore-start -->
 
 <CodeSnippets
   paths={[
-    'react/reuse-args-test.js.mdx',
-    'react/reuse-args-test.ts.mdx',
     'vue/reuse-args-test.3.js.mdx',
     'vue/reuse-args-test.3.ts.mdx',
   ]}
@@ -199,6 +208,8 @@ When using the `composeStories` or `composeStory` functions, the components bein
 
 <!-- prettier-ignore-end -->
 
+</IfRenderer>
+
 #### Learn about other UI tests
 
 - [Test runner](./test-runner.md) to automate test execution