From 30de294cae6bee0874b416fe18d9988ef5cc70cf Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 11:42:57 +0200
Subject: [PATCH 01/11] Try another mock naming convention
---
.../nextjs/src/export-mocks/cache/index.ts | 4 +-
.../src/export-mocks/headers/cookies.ts | 112 ++----------------
.../src/export-mocks/headers/headers.ts | 98 ++-------------
.../src/export-mocks/navigation/index.ts | 59 ++++-----
.../nextjs/src/export-mocks/router/index.ts | 30 +++--
5 files changed, 64 insertions(+), 239 deletions(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/cache/index.ts b/code/frameworks/nextjs/src/export-mocks/cache/index.ts
index 1692979f015..b9f2fa8dd43 100644
--- a/code/frameworks/nextjs/src/export-mocks/cache/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/cache/index.ts
@@ -3,8 +3,8 @@ import { unstable_cache } from 'next/dist/server/web/spec-extension/unstable-cac
import { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store';
// mock utilities/overrides (as of Next v14.2.0)
-const revalidatePath = fn().mockName('revalidatePath');
-const revalidateTag = fn().mockName('revalidateTag');
+const revalidatePath = fn().mockName('next/cache::revalidatePath');
+const revalidateTag = fn().mockName('next/cache::revalidateTag');
const cacheExports = {
unstable_cache,
diff --git a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
index 75022baaea2..c3272dc0e33 100644
--- a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
+++ b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
@@ -1,116 +1,22 @@
-/* eslint-disable no-underscore-dangle */
import { fn } from '@storybook/test';
-import type { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
-import {
- parseCookie,
- stringifyCookie,
- type RequestCookie,
-} from 'next/dist/compiled/@edge-runtime/cookies';
+import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
// We need this import to be a singleton, and because it's used in multiple entrypoints
// both in ESM and CJS, importing it via the package name instead of having a local import
// is the only way to achieve it actually being a singleton
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore we must ignore types here as during compilation they are not generated yet
-import { headers, type HeadersStore } from '@storybook/nextjs/headers.mock';
+import { headers } from '@storybook/nextjs/headers.mock';
-const stringifyCookies = (map: Map) => {
- return Array.from(map)
- .map(([_, v]) => stringifyCookie(v).replace(/; /, ''))
- .join('; ');
-};
-
-// Mostly copied from https://github.com/vercel/edge-runtime/blob/c25e2ded39104e2a3be82efc08baf8dc8fb436b3/packages/cookies/src/request-cookies.ts#L7
-class RequestCookiesMock implements RequestCookies {
- /** @internal */
- private readonly _headers: HeadersStore;
-
- _parsed: Map = new Map();
-
- constructor(requestHeaders: HeadersStore) {
- this._headers = requestHeaders;
- const header = requestHeaders?.get('cookie');
- if (header) {
- const parsed = parseCookie(header);
- for (const [name, value] of parsed) {
- this._parsed.set(name, { name, value });
- }
- }
- }
-
- [Symbol.iterator]() {
- return this._parsed[Symbol.iterator]();
- }
-
- get size(): number {
- return this._parsed.size;
- }
+class RequestCookiesMock extends RequestCookies {
+ get = fn(super.get).mockName('next/headers::get');
- get = fn((...args: [name: string] | [RequestCookie]) => {
- const name = typeof args[0] === 'string' ? args[0] : args[0].name;
- return this._parsed.get(name);
- }).mockName('cookies().get');
+ getAll = fn(super.getAll).mockName('next/headers::cookies().getAll');
- getAll = fn((...args: [name: string] | [RequestCookie] | []) => {
- const all = Array.from(this._parsed);
- if (!args.length) {
- return all.map(([_, value]) => value);
- }
+ has = fn(super.has).mockName('next/headers::cookies().has');
- const name = typeof args[0] === 'string' ? args[0] : args[0]?.name;
- return all.filter(([n]) => n === name).map(([_, value]) => value);
- }).mockName('cookies().getAll');
+ set = fn(super.set).mockName('next/headers::cookies().set');
- has = fn((name: string) => {
- return this._parsed.has(name);
- }).mockName('cookies().has');
-
- set = fn((...args: [key: string, value: string] | [options: RequestCookie]): this => {
- const [name, value] = args.length === 1 ? [args[0].name, args[0].value] : args;
-
- const map = this._parsed;
- map.set(name, { name, value });
-
- this._headers.set('cookie', stringifyCookies(map));
- return this;
- }).mockName('cookies().set');
-
- /**
- * Delete the cookies matching the passed name or names in the request.
- */
- delete = fn(
- (
- /** Name or names of the cookies to be deleted */
- names: string | string[]
- ): boolean | boolean[] => {
- const map = this._parsed;
- const result = !Array.isArray(names)
- ? map.delete(names)
- : names.map((name) => map.delete(name));
- this._headers.set('cookie', stringifyCookies(map));
- return result;
- }
- ).mockName('cookies().delete');
-
- /**
- * Delete all the cookies in the cookies in the request.
- */
- clear = fn((): this => {
- this.delete(Array.from(this._parsed.keys()));
- return this;
- }).mockName('cookies().clear');
-
- /**
- * Format the cookies in the request as a string for logging
- */
- [Symbol.for('edge-runtime.inspect.custom')]() {
- return `RequestCookies ${JSON.stringify(Object.fromEntries(this._parsed))}`;
- }
-
- toString() {
- return [...this._parsed.values()]
- .map((v) => `${v.name}=${encodeURIComponent(v.value)}`)
- .join('; ');
- }
+ delete = fn(super.delete).mockName('next/headers::cookies().delete');
}
let requestCookiesMock: RequestCookiesMock;
@@ -120,7 +26,7 @@ export const cookies = fn(() => {
requestCookiesMock = new RequestCookiesMock(headers());
}
return requestCookiesMock;
-});
+}).mockName('next/headers::cookies()');
const originalRestore = cookies.mockRestore.bind(null);
diff --git a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
index a7511064fa1..02703265e58 100644
--- a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
+++ b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
@@ -1,101 +1,29 @@
import { fn } from '@storybook/test';
-import type { IncomingHttpHeaders } from 'http';
-import type { HeadersAdapter } from 'next/dist/server/web/spec-extension/adapters/headers';
-// Mostly copied from https://github.com/vercel/next.js/blob/763b9a660433ec5278a10e59d7ae89d4010ba212/packages/next/src/server/web/spec-extension/adapters/headers.ts#L20
-// @ts-expect-error unfortunately the headers property is private (and not protected) in HeadersAdapter
-// and we can't access it so we need to redefine it, but that clashes with the type, hence the ts-expect-error comment.
-class HeadersAdapterMock extends Headers implements HeadersAdapter {
- private headers: IncomingHttpHeaders = {};
+import { HeadersAdapter } from 'next/dist/server/web/spec-extension/adapters/headers';
- /**
- * Merges a header value into a string. This stores multiple values as an
- * array, so we need to merge them into a string.
- *
- * @param value a header value
- * @returns a merged header value (a string)
- */
- private merge(value: string | string[]): string {
- if (Array.isArray(value)) return value.join(', ');
-
- return value;
+class HeadersAdapterMock extends HeadersAdapter {
+ constructor() {
+ super({});
}
- public append = fn((name: string, value: string): void => {
- const existing = this.headers[name];
- if (typeof existing === 'string') {
- this.headers[name] = [existing, value];
- } else if (Array.isArray(existing)) {
- existing.push(value);
- } else {
- this.headers[name] = value;
- }
- }).mockName('headers().append');
-
- public delete = fn((name: string) => {
- delete this.headers[name];
- }).mockName('headers().delete');
-
- public get = fn((name: string): string | null => {
- const value = this.headers[name];
- if (typeof value !== 'undefined') return this.merge(value);
+ append = fn(super.append).mockName('next/headers::headers().append');
- return null;
- }).mockName('headers().get');
+ delete = fn(super.delete).mockName('next/headers::headers().delete');
- public has = fn((name: string): boolean => {
- return typeof this.headers[name] !== 'undefined';
- }).mockName('headers().has');
+ get = fn(super.get).mockName('next/headers::headers().get');
- public set = fn((name: string, value: string): void => {
- this.headers[name] = value;
- }).mockName('headers().set');
+ has = fn(super.has).mockName('next/headers::headers().has');
- public forEach = fn(
- (callbackfn: (value: string, name: string, parent: Headers) => void, thisArg?: any): void => {
- for (const [name, value] of this.entries()) {
- callbackfn.call(thisArg, value, name, this);
- }
- }
- ).mockName('headers().forEach');
+ set = fn(super.set).mockName('next/headers::headers().set');
- public entries = fn(
- function* (this: HeadersAdapterMock): IterableIterator<[string, string]> {
- for (const key of Object.keys(this.headers)) {
- const name = key.toLowerCase();
- // We assert here that this is a string because we got it from the
- // Object.keys() call above.
- const value = this.get(name) as string;
+ forEach = fn(super.forEach).mockName('next/headers::headers().forEach');
- yield [name, value];
- }
- }.bind(this)
- ).mockName('headers().entries');
+ entries = fn(super.entries).mockName('next/headers::headers().entries');
- public keys = fn(
- function* (this: HeadersAdapterMock): IterableIterator {
- for (const key of Object.keys(this.headers)) {
- const name = key.toLowerCase();
- yield name;
- }
- }.bind(this)
- ).mockName('headers().keys');
+ keys = fn(super.keys).mockName('next/headers::headers().keys');
- public values = fn(
- function* (this: HeadersAdapterMock): IterableIterator {
- for (const key of Object.keys(this.headers)) {
- // We assert here that this is a string because we got it from the
- // Object.keys() call above.
- const value = this.get(key) as string;
-
- yield value;
- }
- }.bind(this)
- ).mockName('headers().values');
-
- public [Symbol.iterator](): IterableIterator<[string, string]> {
- return this.entries();
- }
+ values = fn(super.values).mockName('next/headers::headers().values');
}
let headersAdapterMock: HeadersAdapterMock;
diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
index 47a7e5801b5..fbbeb8ced25 100644
--- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
@@ -17,14 +17,14 @@ let navigationAPI: {
* @ignore
* @internal
* */
-const createNavigation = (overrides: any) => {
+export const createNavigation = (overrides: any) => {
const navigationActions = {
- push: fn().mockName('useRouter().push'),
- replace: fn().mockName('useRouter().replace'),
- forward: fn().mockName('useRouter().forward'),
- back: fn().mockName('useRouter().back'),
- prefetch: fn().mockName('useRouter().prefetch'),
- refresh: fn().mockName('useRouter().refresh'),
+ push: fn().mockName('next/navigation::useRouter().push'),
+ replace: fn().mockName('next/navigation::useRouter().replace'),
+ forward: fn().mockName('next/navigation::useRouter().forward'),
+ back: fn().mockName('next/navigation::useRouter().back'),
+ prefetch: fn().mockName('next/navigation::useRouter().prefetch'),
+ refresh: fn().mockName('next/navigation::useRouter().refresh'),
};
if (overrides) {
@@ -42,7 +42,7 @@ const createNavigation = (overrides: any) => {
return navigationAPI;
};
-const getRouter = () => {
+export const getRouter = () => {
if (!navigationAPI) {
throw new NextjsRouterMocksNotAvailable({
importType: 'next/navigation',
@@ -56,41 +56,34 @@ const getRouter = () => {
export * from 'next/dist/client/components/navigation';
// mock utilities/overrides (as of Next v14.2.0)
-const redirect = fn().mockName('redirect');
+export const redirect = fn().mockName('next/navigation::redirect');
// passthrough mocks - keep original implementation but allow for spying
-const useSearchParams = fn(originalNavigation.useSearchParams).mockName('useSearchParams');
-const usePathname = fn(originalNavigation.usePathname).mockName('usePathname');
-const useSelectedLayoutSegment = fn(originalNavigation.useSelectedLayoutSegment).mockName(
+export const useSearchParams = fn(originalNavigation.useSearchParams).mockName(
+ 'next/navigation::useSearchParams'
+);
+export const usePathname = fn(originalNavigation.usePathname).mockName(
+ 'next/navigation::usePathname'
+);
+export const useSelectedLayoutSegment = fn(originalNavigation.useSelectedLayoutSegment).mockName(
'useSelectedLayoutSegment'
);
-const useSelectedLayoutSegments = fn(originalNavigation.useSelectedLayoutSegments).mockName(
+export const useSelectedLayoutSegments = fn(originalNavigation.useSelectedLayoutSegments).mockName(
'useSelectedLayoutSegments'
);
-const useRouter = fn(originalNavigation.useRouter).mockName('useRouter');
-const useServerInsertedHTML = fn(originalNavigation.useServerInsertedHTML).mockName(
+export const useRouter = fn(originalNavigation.useRouter).mockName('next/navigation::useRouter');
+export const useServerInsertedHTML = fn(originalNavigation.useServerInsertedHTML).mockName(
'useServerInsertedHTML'
);
-const notFound = fn(originalNavigation.notFound).mockName('notFound');
-const permanentRedirect = fn(originalNavigation.permanentRedirect).mockName('permanentRedirect');
+export const notFound = fn(originalNavigation.notFound).mockName('next/navigation::notFound');
+export const permanentRedirect = fn(originalNavigation.permanentRedirect).mockName(
+ 'permanentRedirect'
+);
// Params, not exported by Next.js, is manually declared to avoid inference issues.
interface Params {
[key: string]: string | string[];
}
-const useParams = fn<[], Params>(originalNavigation.useParams).mockName('useParams');
-
-export {
- createNavigation,
- getRouter,
- redirect,
- useSearchParams,
- usePathname,
- useSelectedLayoutSegment,
- useSelectedLayoutSegments,
- useParams,
- useRouter,
- useServerInsertedHTML,
- notFound,
- permanentRedirect,
-};
+export const useParams = fn<[], Params>(originalNavigation.useParams).mockName(
+ 'next/navigation::useParams'
+);
diff --git a/code/frameworks/nextjs/src/export-mocks/router/index.ts b/code/frameworks/nextjs/src/export-mocks/router/index.ts
index c9f81f3a72b..b3c5e37faa4 100644
--- a/code/frameworks/nextjs/src/export-mocks/router/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/router/index.ts
@@ -36,27 +36,27 @@ let routerAPI: {
* @ignore
* @internal
* */
-const createRouter = (overrides: Partial) => {
+export const createRouter = (overrides: Partial) => {
const routerActions: Partial = {
push: fn((..._args: any[]) => {
return Promise.resolve(true);
- }).mockName('useRouter().push'),
+ }).mockName('next/router::useRouter().push'),
replace: fn((..._args: any[]) => {
return Promise.resolve(true);
- }).mockName('useRouter().replace'),
- reload: fn((..._args: any[]) => {}).mockName('useRouter().reload'),
- back: fn((..._args: any[]) => {}).mockName('useRouter().back'),
- forward: fn(() => {}).mockName('useRouter().forward'),
+ }).mockName('next/router::useRouter().replace'),
+ reload: fn((..._args: any[]) => {}).mockName('next/router::useRouter().reload'),
+ back: fn((..._args: any[]) => {}).mockName('next/router::useRouter().back'),
+ forward: fn(() => {}).mockName('next/router::useRouter().forward'),
prefetch: fn((..._args: any[]) => {
return Promise.resolve();
- }).mockName('useRouter().prefetch'),
- beforePopState: fn((..._args: any[]) => {}).mockName('useRouter().beforePopState'),
+ }).mockName('next/router::useRouter().prefetch'),
+ beforePopState: fn((..._args: any[]) => {}).mockName('next/router::useRouter().beforePopState'),
};
const routerEvents: NextRouter['events'] = {
- on: fn((..._args: any[]) => {}).mockName('useRouter().events.on'),
- off: fn((..._args: any[]) => {}).mockName('useRouter().events.off'),
- emit: fn((..._args: any[]) => {}).mockName('useRouter().events.emit'),
+ on: fn((..._args: any[]) => {}).mockName('next/router::useRouter().events.on'),
+ off: fn((..._args: any[]) => {}).mockName('next/router::useRouter().events.off'),
+ emit: fn((..._args: any[]) => {}).mockName('next/router::useRouter().events.emit'),
};
if (overrides) {
@@ -95,7 +95,7 @@ const createRouter = (overrides: Partial) => {
return routerAPI as unknown as NextRouter;
};
-const getRouter = () => {
+export const getRouter = () => {
if (!routerAPI) {
throw new NextjsRouterMocksNotAvailable({
importType: 'next/router',
@@ -111,7 +111,5 @@ export default singletonRouter;
// mock utilities/overrides (as of Next v14.2.0)
// passthrough mocks - keep original implementation but allow for spying
-const useRouter = fn(originalRouter.useRouter).mockName('useRouter');
-const withRouter = fn(originalRouter.withRouter).mockName('withRouter');
-
-export { createRouter, getRouter, useRouter, withRouter };
+export const useRouter = fn(originalRouter.useRouter).mockName('next/router::useRouter');
+export const withRouter = fn(originalRouter.withRouter).mockName('next/router::withRouter');
From 310aaf5aaffd0cdc14d2afe86340bb6f44aefbd2 Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 12:11:13 +0200
Subject: [PATCH 02/11] Bind this
---
.../nextjs/src/export-mocks/headers/cookies.ts | 10 +++++-----
.../nextjs/src/export-mocks/headers/headers.ts | 18 +++++++++---------
.../nextjs/yarn.lock | 8 ++++----
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
index c3272dc0e33..3fc9fdc1ae5 100644
--- a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
+++ b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
@@ -8,15 +8,15 @@ import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
import { headers } from '@storybook/nextjs/headers.mock';
class RequestCookiesMock extends RequestCookies {
- get = fn(super.get).mockName('next/headers::get');
+ get = fn(super.get.bind(this)).mockName('next/headers::get');
- getAll = fn(super.getAll).mockName('next/headers::cookies().getAll');
+ getAll = fn(super.getAll.bind(this)).mockName('next/headers::cookies().getAll');
- has = fn(super.has).mockName('next/headers::cookies().has');
+ has = fn(super.has.bind(this)).mockName('next/headers::cookies().has');
- set = fn(super.set).mockName('next/headers::cookies().set');
+ set = fn(super.set.bind(this)).mockName('next/headers::cookies().set');
- delete = fn(super.delete).mockName('next/headers::cookies().delete');
+ delete = fn(super.delete.bind(this)).mockName('next/headers::cookies().delete');
}
let requestCookiesMock: RequestCookiesMock;
diff --git a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
index 02703265e58..d9eb5177b44 100644
--- a/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
+++ b/code/frameworks/nextjs/src/export-mocks/headers/headers.ts
@@ -7,23 +7,23 @@ class HeadersAdapterMock extends HeadersAdapter {
super({});
}
- append = fn(super.append).mockName('next/headers::headers().append');
+ append = fn(super.append.bind(this)).mockName('next/headers::headers().append');
- delete = fn(super.delete).mockName('next/headers::headers().delete');
+ delete = fn(super.delete.bind(this)).mockName('next/headers::headers().delete');
- get = fn(super.get).mockName('next/headers::headers().get');
+ get = fn(super.get.bind(this)).mockName('next/headers::headers().get');
- has = fn(super.has).mockName('next/headers::headers().has');
+ has = fn(super.has.bind(this)).mockName('next/headers::headers().has');
- set = fn(super.set).mockName('next/headers::headers().set');
+ set = fn(super.set.bind(this)).mockName('next/headers::headers().set');
- forEach = fn(super.forEach).mockName('next/headers::headers().forEach');
+ forEach = fn(super.forEach.bind(this)).mockName('next/headers::headers().forEach');
- entries = fn(super.entries).mockName('next/headers::headers().entries');
+ entries = fn(super.entries.bind(this)).mockName('next/headers::headers().entries');
- keys = fn(super.keys).mockName('next/headers::headers().keys');
+ keys = fn(super.keys.bind(this)).mockName('next/headers::headers().keys');
- values = fn(super.values).mockName('next/headers::headers().values');
+ values = fn(super.values.bind(this)).mockName('next/headers::headers().values');
}
let headersAdapterMock: HeadersAdapterMock;
diff --git a/test-storybooks/portable-stories-kitchen-sink/nextjs/yarn.lock b/test-storybooks/portable-stories-kitchen-sink/nextjs/yarn.lock
index e0efcfd9d6d..71f8b86f980 100644
--- a/test-storybooks/portable-stories-kitchen-sink/nextjs/yarn.lock
+++ b/test-storybooks/portable-stories-kitchen-sink/nextjs/yarn.lock
@@ -3167,7 +3167,7 @@ __metadata:
"@storybook/nextjs@file:../../../code/frameworks/nextjs::locator=portable-stories-nextjs%40workspace%3A.":
version: 8.1.0-alpha.7
- resolution: "@storybook/nextjs@file:../../../code/frameworks/nextjs#../../../code/frameworks/nextjs::hash=246816&locator=portable-stories-nextjs%40workspace%3A."
+ resolution: "@storybook/nextjs@file:../../../code/frameworks/nextjs#../../../code/frameworks/nextjs::hash=28a407&locator=portable-stories-nextjs%40workspace%3A."
dependencies:
"@babel/core": "npm:^7.23.2"
"@babel/plugin-syntax-bigint": "npm:^7.8.3"
@@ -3227,7 +3227,7 @@ __metadata:
optional: true
webpack:
optional: true
- checksum: 10/71732cc220e381872106dab3824883f4a77dcbb60901c939f58599bf92f156564a34fe646ce1159c307702be03cf532fbffaa1a515e271a6623f340d19000283
+ checksum: 10/fd9a469074e0b7aba065a0b0f81f272e75e708370362ff047a653d9a19c5b753fcfab8b2f30b3f9ae226a12739b7b11054358afe4707e8d7185b9dca11c75a7c
languageName: node
linkType: hard
@@ -3326,7 +3326,7 @@ __metadata:
"@storybook/react@file:../../../code/renderers/react::locator=portable-stories-nextjs%40workspace%3A.":
version: 8.1.0-alpha.7
- resolution: "@storybook/react@file:../../../code/renderers/react#../../../code/renderers/react::hash=cd73fa&locator=portable-stories-nextjs%40workspace%3A."
+ resolution: "@storybook/react@file:../../../code/renderers/react#../../../code/renderers/react::hash=faf3f4&locator=portable-stories-nextjs%40workspace%3A."
dependencies:
"@storybook/client-logger": "workspace:*"
"@storybook/docs-tools": "workspace:*"
@@ -3356,7 +3356,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 10/834084c0092a8b179f7048c1111308b6a2381cf3ee119372ed2940833b02e13577b5bc334c3f14c3224bd2d8b786939a74fbaf4dea6e8423ff610b34047412b4
+ checksum: 10/f89fb42e87e17377af48b57b337dd4708053ae83d8558a0ae35af479b1faa6d7206b07934e18113707febed5ebcf94510caa89b8c92bc87cf7b5391296bbfef2
languageName: node
linkType: hard
From 0b243bd26d08c2b8f5aa32df503403d1baf93563 Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 13:02:34 +0200
Subject: [PATCH 03/11] Update snapshot
---
.../nextjs/stories/__snapshots__/portable-stories.test.tsx.snap | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test-storybooks/portable-stories-kitchen-sink/nextjs/stories/__snapshots__/portable-stories.test.tsx.snap b/test-storybooks/portable-stories-kitchen-sink/nextjs/stories/__snapshots__/portable-stories.test.tsx.snap
index 2b8af2b9cd5..a22fa06a8ab 100644
--- a/test-storybooks/portable-stories-kitchen-sink/nextjs/stories/__snapshots__/portable-stories.test.tsx.snap
+++ b/test-storybooks/portable-stories-kitchen-sink/nextjs/stories/__snapshots__/portable-stories.test.tsx.snap
@@ -794,7 +794,7 @@ exports[`renders nextHeaderStories stories renders Default 1`] = `
- firstName=Jane; lastName=Doe
+ firstName=Jane; ; lastName=Doe;
Date: Tue, 16 Apr 2024 13:11:55 +0200
Subject: [PATCH 04/11] Fix name
---
code/frameworks/nextjs/src/export-mocks/headers/cookies.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
index 3fc9fdc1ae5..3d84ecba388 100644
--- a/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
+++ b/code/frameworks/nextjs/src/export-mocks/headers/cookies.ts
@@ -8,7 +8,7 @@ import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
import { headers } from '@storybook/nextjs/headers.mock';
class RequestCookiesMock extends RequestCookies {
- get = fn(super.get.bind(this)).mockName('next/headers::get');
+ get = fn(super.get.bind(this)).mockName('next/headers::cookies().get');
getAll = fn(super.getAll.bind(this)).mockName('next/headers::cookies().getAll');
From b51db447ed09e16d19cc734787552680eb42b343 Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:08:31 +0200
Subject: [PATCH 05/11] Hide some junk of next for nwo
---
code/addons/actions/src/loaders.ts | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts
index d49a048da23..a1fff870b7b 100644
--- a/code/addons/actions/src/loaders.ts
+++ b/code/addons/actions/src/loaders.ts
@@ -18,7 +18,19 @@ const logActionsWhenMockCalled: LoaderFunction = (context) => {
typeof global.__STORYBOOK_TEST_ON_MOCK_CALL__ === 'function'
) {
const onMockCall = global.__STORYBOOK_TEST_ON_MOCK_CALL__ as typeof onMockCallType;
- onMockCall((mock, args) => action(mock.getMockName())(args));
+ onMockCall((mock, args) => {
+ const name = mock.getMockName();
+
+ // TODO: Make this a configurable API in 8.2
+ if (
+ !/^next\/.*::/.test(name) ||
+ ((name.startsWith('next/headers::cookies()') ||
+ name.startsWith('next/headers::headers()')) &&
+ (name.endsWith('set') || name.endsWith('delete')))
+ ) {
+ action(name)(args);
+ }
+ });
subscribed = true;
}
};
From a1d631b8748f7d08b44f97a67c0953aef9f1af3a Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:13:47 +0200
Subject: [PATCH 06/11] Update
code/frameworks/nextjs/src/export-mocks/navigation/index.ts
Co-authored-by: Yann Braga
---
code/frameworks/nextjs/src/export-mocks/navigation/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
index fbbeb8ced25..61344102c24 100644
--- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
@@ -77,7 +77,7 @@ export const useServerInsertedHTML = fn(originalNavigation.useServerInsertedHTML
);
export const notFound = fn(originalNavigation.notFound).mockName('next/navigation::notFound');
export const permanentRedirect = fn(originalNavigation.permanentRedirect).mockName(
- 'permanentRedirect'
+ 'next/navigation::permanentRedirect'
);
// Params, not exported by Next.js, is manually declared to avoid inference issues.
From 2beb7ba087f771ee85d1126d5cc025359853b2d3 Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:13:53 +0200
Subject: [PATCH 07/11] Update
code/frameworks/nextjs/src/export-mocks/navigation/index.ts
Co-authored-by: Yann Braga
---
code/frameworks/nextjs/src/export-mocks/navigation/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
index 61344102c24..2973c65120e 100644
--- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
@@ -66,7 +66,7 @@ export const usePathname = fn(originalNavigation.usePathname).mockName(
'next/navigation::usePathname'
);
export const useSelectedLayoutSegment = fn(originalNavigation.useSelectedLayoutSegment).mockName(
- 'useSelectedLayoutSegment'
+ 'next/navigation::useSelectedLayoutSegment'
);
export const useSelectedLayoutSegments = fn(originalNavigation.useSelectedLayoutSegments).mockName(
'useSelectedLayoutSegments'
From d83691a92415159962ce34fef32ebb6fef3d6cba Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:14:02 +0200
Subject: [PATCH 08/11] Update
code/frameworks/nextjs/src/export-mocks/navigation/index.ts
Co-authored-by: Yann Braga
---
code/frameworks/nextjs/src/export-mocks/navigation/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
index 2973c65120e..63458b0fc92 100644
--- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
@@ -73,7 +73,7 @@ export const useSelectedLayoutSegments = fn(originalNavigation.useSelectedLayout
);
export const useRouter = fn(originalNavigation.useRouter).mockName('next/navigation::useRouter');
export const useServerInsertedHTML = fn(originalNavigation.useServerInsertedHTML).mockName(
- 'useServerInsertedHTML'
+ 'next/navigation::useServerInsertedHTML'
);
export const notFound = fn(originalNavigation.notFound).mockName('next/navigation::notFound');
export const permanentRedirect = fn(originalNavigation.permanentRedirect).mockName(
From 1aa833d1a3cd079433f004d8f3f464b2579eb3ab Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:14:07 +0200
Subject: [PATCH 09/11] Update
code/frameworks/nextjs/src/export-mocks/navigation/index.ts
Co-authored-by: Yann Braga
---
code/frameworks/nextjs/src/export-mocks/navigation/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
index 63458b0fc92..dd9e9a692e6 100644
--- a/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
+++ b/code/frameworks/nextjs/src/export-mocks/navigation/index.ts
@@ -69,7 +69,7 @@ export const useSelectedLayoutSegment = fn(originalNavigation.useSelectedLayoutS
'next/navigation::useSelectedLayoutSegment'
);
export const useSelectedLayoutSegments = fn(originalNavigation.useSelectedLayoutSegments).mockName(
- 'useSelectedLayoutSegments'
+ 'next/navigation::useSelectedLayoutSegments'
);
export const useRouter = fn(originalNavigation.useRouter).mockName('next/navigation::useRouter');
export const useServerInsertedHTML = fn(originalNavigation.useServerInsertedHTML).mockName(
From 8b6bbbfefcd640434944a2d478e258ad6b54a1cd Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 14:19:52 +0200
Subject: [PATCH 10/11] Hide some junk of next for now
---
code/addons/actions/src/loaders.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts
index a1fff870b7b..7f279bba577 100644
--- a/code/addons/actions/src/loaders.ts
+++ b/code/addons/actions/src/loaders.ts
@@ -24,6 +24,8 @@ const logActionsWhenMockCalled: LoaderFunction = (context) => {
// TODO: Make this a configurable API in 8.2
if (
!/^next\/.*::/.test(name) ||
+ name.startsWith('next/router::useRouter()') ||
+ name.startsWith('next/navigation::useRouter()') ||
((name.startsWith('next/headers::cookies()') ||
name.startsWith('next/headers::headers()')) &&
(name.endsWith('set') || name.endsWith('delete')))
From 8dbd04c4c73b6a55fc9e77b129435fc8fde0e7be Mon Sep 17 00:00:00 2001
From: Kasper Peulen
Date: Tue, 16 Apr 2024 15:09:15 +0200
Subject: [PATCH 11/11] Show redirect and next/cache spies
---
code/addons/actions/src/loaders.ts | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/code/addons/actions/src/loaders.ts b/code/addons/actions/src/loaders.ts
index 7f279bba577..eebb09acb71 100644
--- a/code/addons/actions/src/loaders.ts
+++ b/code/addons/actions/src/loaders.ts
@@ -24,11 +24,16 @@ const logActionsWhenMockCalled: LoaderFunction = (context) => {
// TODO: Make this a configurable API in 8.2
if (
!/^next\/.*::/.test(name) ||
- name.startsWith('next/router::useRouter()') ||
- name.startsWith('next/navigation::useRouter()') ||
- ((name.startsWith('next/headers::cookies()') ||
- name.startsWith('next/headers::headers()')) &&
- (name.endsWith('set') || name.endsWith('delete')))
+ [
+ 'next/router::useRouter()',
+ 'next/navigation::useRouter()',
+ 'next/navigation::redirect',
+ 'next/cache::',
+ 'next/headers::cookies().set',
+ 'next/headers::cookies().delete',
+ 'next/headers::headers().set',
+ 'next/headers::headers().delete',
+ ].some((prefix) => name.startsWith(prefix))
) {
action(name)(args);
}