From fa533f17745f493c3046f326f63379f9f4adcafb Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Tue, 12 Nov 2024 14:14:05 +0100 Subject: [PATCH] move more stories out of next 13 --- .../GetImageProps.stories.tsx | 0 .../NextHeader.stories.tsx | 0 .../NextHeader.tsx | 0 .../Redirect.stories.tsx | 0 .../GetImageProps.stories.tsx | 36 ++++++++++++ .../NextHeader.stories.tsx | 51 +++++++++++++++++ .../stories_nextjs-prerelease/NextHeader.tsx | 38 +++++++++++++ .../Redirect.stories.tsx | 57 +++++++++++++++++++ 8 files changed, 182 insertions(+) rename code/frameworks/nextjs/template/{stories => stories_nextjs-default-ts}/GetImageProps.stories.tsx (100%) rename code/frameworks/nextjs/template/{stories => stories_nextjs-default-ts}/NextHeader.stories.tsx (100%) rename code/frameworks/nextjs/template/{stories => stories_nextjs-default-ts}/NextHeader.tsx (100%) rename code/frameworks/nextjs/template/{stories => stories_nextjs-default-ts}/Redirect.stories.tsx (100%) create mode 100644 code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx create mode 100644 code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx create mode 100644 code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx create mode 100644 code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx diff --git a/code/frameworks/nextjs/template/stories/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories/GetImageProps.stories.tsx rename to code/frameworks/nextjs/template/stories_nextjs-default-ts/GetImageProps.stories.tsx diff --git a/code/frameworks/nextjs/template/stories/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories/NextHeader.stories.tsx rename to code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.stories.tsx diff --git a/code/frameworks/nextjs/template/stories/NextHeader.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories/NextHeader.tsx rename to code/frameworks/nextjs/template/stories_nextjs-default-ts/NextHeader.tsx diff --git a/code/frameworks/nextjs/template/stories/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx similarity index 100% rename from code/frameworks/nextjs/template/stories/Redirect.stories.tsx rename to code/frameworks/nextjs/template/stories_nextjs-default-ts/Redirect.stories.tsx diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx new file mode 100644 index 000000000000..aefc27f54cfd --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/GetImageProps.stories.tsx @@ -0,0 +1,36 @@ +import React from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; + +import { getImageProps } from 'next/image'; + +import Accessibility from '../../assets/accessibility.svg'; +import Testing from '../../assets/testing.png'; + +// referenced from https://nextjs.org/docs/pages/api-reference/components/image#theme-detection-picture +const Component = (props: any) => { + const { + props: { srcSet: dark }, + } = getImageProps({ src: Accessibility, ...props }); + const { + // capture rest on one to spread to img as default; it doesn't matter which barring art direction + props: { srcSet: light, ...rest }, + } = getImageProps({ src: Testing, ...props }); + + return ( + + + + + + ); +}; + +export default { + component: Component, + args: { + alt: 'getImageProps Example', + }, +} as Meta; + +export const Default: StoryObj = {}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx new file mode 100644 index 000000000000..f5e83ef867f6 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.stories.tsx @@ -0,0 +1,51 @@ +import { cookies, headers } from '@storybook/nextjs/headers.mock'; +import type { Meta, StoryObj } from '@storybook/react'; +import { expect, userEvent, within } from '@storybook/test'; + +import NextHeader from './NextHeader'; + +export default { + component: NextHeader, + parameters: { + react: { + rsc: true, + }, + }, +} as Meta; + +type Story = StoryObj; + +export const Default: Story = { + loaders: async () => { + cookies().set('firstName', 'Jane'); + cookies().set({ + name: 'lastName', + value: 'Doe', + }); + headers().set('timezone', 'Central European Summer Time'); + }, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + const headersMock = headers(); + const cookiesMock = cookies(); + await step('Cookie and header store apis are called upon rendering', async () => { + await expect(cookiesMock.getAll).toHaveBeenCalled(); + await expect(headersMock.entries).toHaveBeenCalled(); + }); + + await step('Upon clicking on submit, the user-id cookie is set', async () => { + const submitButton = await canvas.findByRole('button'); + await userEvent.click(submitButton); + + await expect(cookiesMock.set).toHaveBeenCalledWith('user-id', 'encrypted-id'); + }); + + await step('The user-id cookie is available in cookie and header stores', async () => { + await expect(headersMock.get('cookie')).toContain('user-id=encrypted-id'); + await expect(cookiesMock.get('user-id')).toEqual({ + name: 'user-id', + value: 'encrypted-id', + }); + }); + }, +}; diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx new file mode 100644 index 000000000000..eca7197ed79a --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/NextHeader.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +import { cookies, headers } from 'next/headers'; + +export default async function Component() { + async function handleClick() { + 'use server'; + (await cookies()).set('user-id', 'encrypted-id'); + } + + return ( + <> +

Cookies:

+ {(await cookies()).getAll().map(({ name, value }) => { + return ( +

+ Name: {name} + Value: {value} +

+ ); + })} + +

Headers:

+ {Array.from((await headers()).entries()).map(([name, value]: [string, string]) => { + return ( +

+ Name: {name} + Value: {value} +

+ ); + })} + +
+ +
+ + ); +} diff --git a/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx new file mode 100644 index 000000000000..3c5980b79757 --- /dev/null +++ b/code/frameworks/nextjs/template/stories_nextjs-prerelease/Redirect.stories.tsx @@ -0,0 +1,57 @@ +import React from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; +import { userEvent, within } from '@storybook/test'; + +import { redirect } from 'next/navigation'; + +let state = 'Bug! Not invalidated'; + +export default { + render() { + return ( +
+
{state}
+
{ + state = 'State is invalidated successfully.'; + redirect('/'); + }} + > + +
+
+ ); + }, + parameters: { + test: { + // This is needed until Next will update to the React 19 beta: https://github.com/vercel/next.js/pull/65058 + // In the React 19 beta ErrorBoundary errors (such as redirect) are only logged, and not thrown. + // We will also suspress console.error logs for re the console.error logs for redirect in the next framework. + // Using the onCaughtError react root option: + // react: { + // rootOptions: { + // onCaughtError(error: unknown) { + // if (isNextRouterError(error)) return; + // console.error(error); + // }, + // }, + // See: code/frameworks/nextjs/src/preview.tsx + dangerouslyIgnoreUnhandledErrors: true, + }, + nextjs: { + appDirectory: true, + navigation: { + pathname: '/', + }, + }, + }, + tags: ['!test'], +} as Meta; + +export const SingletonStateGetsInvalidatedAfterRedirecting: StoryObj = { + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole('button')); + }, +};