Merge branch 'release-8-0' into norbert/remove-storiesof

This commit is contained in:
Norbert de Langen 2023-11-02 10:03:27 +01:00 committed by GitHub
commit 3c2dda4bf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
90 changed files with 478 additions and 330 deletions

View File

@ -29,7 +29,7 @@ test.describe('addon-interactions', () => {
await expect(welcome).toContainText('Welcome, Jane Doe!');
const interactionsTab = await page.locator('#tabbutton-storybook-interactions-panel');
await expect(interactionsTab).toContainText(/(1)/);
await expect(interactionsTab).toContainText(/(\d)/);
await expect(interactionsTab).toBeVisible();
const panel = sbPage.panelContent();
@ -37,7 +37,7 @@ test.describe('addon-interactions', () => {
await expect(panel).toContainText(/userEvent.click/);
await expect(panel).toBeVisible();
const done = await panel.locator('[data-testid=icon-done]');
const done = await panel.locator('[data-testid=icon-done]').nth(0);
await expect(done).toBeVisible();
});

View File

@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/angular';
import { moduleMetadata } from '@storybook/angular';
import { within, userEvent } from '@storybook/testing-library';
import { CommonModule } from '@angular/common';
import { within, userEvent, expect } from '@storybook/test';
import Button from './button.component';
import Header from './header.component';
@ -38,9 +38,12 @@ export const LoggedIn: Story = {
}),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -13,10 +13,21 @@ import { defaultLoader } from './next-image-default-loader';
const ImageContext = ImageContextValue as typeof ImageContextType;
const MockedNextImage = ({ loader, ...props }: _NextImage.ImageProps) => {
const imageParameters = React.useContext(ImageContext);
const MockedNextImage = React.forwardRef<HTMLImageElement, _NextImage.ImageProps>(
({ loader, ...props }, ref) => {
const imageParameters = React.useContext(ImageContext);
return <OriginalNextImage {...imageParameters} {...props} loader={loader ?? defaultLoader} />;
};
return (
<OriginalNextImage
ref={ref}
{...imageParameters}
{...props}
loader={loader ?? defaultLoader}
/>
);
}
);
MockedNextImage.displayName = 'NextImage';
export default MockedNextImage;

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
export default {
@ -16,9 +16,12 @@ export const LoggedOut = {};
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useRef, useState } from 'react';
import Image from 'next/image';
import { waitFor } from '@storybook/testing-library';
@ -89,3 +89,16 @@ export const Eager = {
},
},
};
export const WithRef = {
render() {
const [ref, setRef] = useState(null);
return (
<div>
<Image src={Accessibility} alt="Accessibility" ref={setRef} />
<p>Alt attribute of image: {ref?.alt}</p>
</div>
);
},
};

View File

@ -251,7 +251,14 @@ export async function baseGenerator(
if (hasInteractiveStories(rendererId)) {
addons.push('@storybook/addon-interactions');
addonPackages.push('@storybook/addon-interactions', '@storybook/testing-library@^0.2.0-next.0');
addonPackages.push('@storybook/addon-interactions');
// TODO: migrate template stories in solid and qwik to use @storybook/test
if (['solid', 'qwik'].includes(rendererId)) {
addonPackages.push('@storybook/testing-library');
} else {
addonPackages.push('@storybook/test');
}
}
const files = await fse.readdir(process.cwd());

View File

@ -225,10 +225,13 @@ export const frameworkOptions = async (
export const docs = (
docsOptions: StorybookConfig['docs'],
{ docs: docsMode }: CLIOptions
): StorybookConfig['docs'] => ({
...docsOptions,
docsMode,
});
): StorybookConfig['docs'] =>
docsOptions && docsMode !== undefined
? {
...docsOptions,
docsMode,
}
: docsOptions;
export const managerHead = async (_: any, options: Options) => {
const location = join(options.configDir, 'manager-head.html');

View File

@ -2,7 +2,7 @@ import { global as globalThis } from '@storybook/global';
import type { PartialStoryFn, PlayFunctionContext, StoryContext } from '@storybook/types';
import { within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
import { pick } from 'lodash';
import pick from 'lodash/pick';
import { STORY_ARGS_UPDATED, UPDATE_STORY_ARGS, RESET_STORY_ARGS } from '@storybook/core-events';
export default {

View File

@ -15,13 +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';
type Matchers<T> = PromisifyObject<JestAssertion<T>> &
matchers.TestingLibraryMatchers<ReturnType<ExpectStatic['stringContaining']>, Promise<void>>;
// We only expose the jest compatible API for now
export interface Assertion<T>
extends PromisifyObject<JestAssertion<T>>,
TestingLibraryMatchers<ReturnType<ExpectStatic['stringContaining']>, Promise<void>> {
export interface Assertion<T> extends Matchers<T> {
toHaveBeenCalledOnce(): Promise<void>;
toSatisfy<E>(matcher: (value: E) => boolean, message?: string): Promise<void>;
resolves: Assertion<T>;

View File

@ -80,6 +80,7 @@
],
"resolutions": {
"@playwright/test": "1.36.0",
"@testing-library/jest-dom/aria-query": "5.1.3",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/experimental-utils": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",

View File

@ -26,11 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -70,7 +68,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config';

View File

@ -1,7 +0,0 @@
import { parameters as docsParams } from './docs/config';
import type { Parameters } from './types';
export const parameters: Parameters = { renderer: 'html', ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { renderToCanvas, render } from './render';

View File

@ -1,23 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { SourceType, enhanceArgTypes } from '@storybook/docs-tools';
import { sourceDecorator } from './sourceDecorator';
import type { Parameters, StoryFnHtmlReturnType } from '../types';
export const decorators: Addon_DecoratorFunction<StoryFnHtmlReturnType>[] = [
sourceDecorator as Addon_DecoratorFunction<StoryFnHtmlReturnType>,
];
export const parameters: Partial<Parameters> = {
docs: {
story: { inline: true },
source: {
type: SourceType.DYNAMIC,
language: 'html',
code: undefined,
excludeDecorators: undefined,
},
},
};
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -2,13 +2,13 @@
import { SNIPPET_RENDERED, SourceType } from '@storybook/docs-tools';
import { addons, useEffect } from '@storybook/preview-api';
import type { PartialStoryFn } from '@storybook/types';
import type { DecoratorFunction } from '@storybook/types';
import type { HtmlRenderer, StoryContext } from '../types';
import type { HtmlRenderer } from '../types';
import type { StoryFn } from '../public-types';
function skipSourceRender(context: StoryContext) {
function skipSourceRender(context: Parameters<DecoratorFunction<HtmlRenderer>>[1]) {
const sourceParams = context?.parameters.docs?.source;
const isArgsStory = context?.parameters.__isArgsStory;
@ -22,7 +22,7 @@ function skipSourceRender(context: StoryContext) {
return !isArgsStory || sourceParams?.code || sourceParams?.type === SourceType.CODE;
}
export function sourceDecorator(storyFn: PartialStoryFn<HtmlRenderer>, context: StoryContext) {
export const sourceDecorator: DecoratorFunction<HtmlRenderer> = (storyFn, context) => {
const story = storyFn();
const renderedForSource = context?.parameters.docs?.source?.excludeDecorators
? (context.originalStoryFn as StoryFn)(context.args, context)
@ -42,4 +42,4 @@ export function sourceDecorator(storyFn: PartialStoryFn<HtmlRenderer>, context:
});
return story;
}
};

View File

@ -0,0 +1,21 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { SourceType, enhanceArgTypes } from '@storybook/docs-tools';
import { sourceDecorator } from './docs/sourceDecorator';
import type { HtmlRenderer } from './types';
export const decorators: DecoratorFunction<HtmlRenderer>[] = [sourceDecorator];
export const parameters = {
docs: {
story: { inline: true },
source: {
type: SourceType.DYNAMIC,
language: 'html',
code: undefined,
excludeDecorators: undefined,
},
},
};
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -0,0 +1,5 @@
import type { Parameters } from './types';
export const parameters: Parameters = { renderer: 'html' };
export { renderToCanvas, render } from './render';

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { createPage } from './Page';
export default {
@ -16,9 +16,12 @@ export const LoggedOut = {};
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/html';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { createPage } from './Page';
const meta: Meta = {
@ -19,9 +19,12 @@ export const LoggedOut: StoryObj = {};
export const LoggedIn: StoryObj = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/html';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { createPage } from './Page';
const meta = {
@ -19,9 +19,12 @@ export const LoggedOut: StoryObj = {};
export const LoggedIn: StoryObj = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -26,11 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -70,7 +68,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config';

View File

@ -1,5 +0,0 @@
import { parameters as docsParams } from './docs/config';
export { renderToCanvas, render } from './render';
export const parameters: {} = { renderer: 'preact' as const, ...docsParams };

View File

@ -0,0 +1,3 @@
export { renderToCanvas, render } from './render';
export const parameters = { renderer: 'preact' };

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent } from '@storybook/test';
import { Page } from './Page';

View File

@ -26,15 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./dist/preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.js"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -101,8 +95,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts",
"./src/preset.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -1 +0,0 @@
export * from './dist/config.mjs';

View File

@ -1,9 +0,0 @@
import { parameters as docsParams } from './docs/config';
export const parameters: {} = { renderer: 'react', ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { render, renderToCanvas } from './render';
export { applyDecorators } from './applyDecorators';

View File

@ -1,8 +1,8 @@
import { defaultDecorateStory } from '@storybook/preview-api';
import type { LegacyStoryFn, DecoratorFunction } from '@storybook/types';
import type { ReactRenderer } from './types';
import { jsxDecorator } from './docs/jsxDecorator';
import type { ReactRenderer } from '../types';
import { jsxDecorator } from './jsxDecorator';
export const applyDecorators = (
storyFn: LegacyStoryFn<ReactRenderer>,

View File

@ -1,18 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './extractArgTypes';
import { jsxDecorator } from './jsxDecorator';
import type { StoryFnReactReturnType } from '../types';
export const parameters: {} = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: Addon_DecoratorFunction<StoryFnReactReturnType>[] = [jsxDecorator];
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -0,0 +1,20 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './docs/extractArgTypes';
import { jsxDecorator } from './docs/jsxDecorator';
import type { ReactRenderer } from './types';
export const parameters = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: DecoratorFunction<ReactRenderer>[] = [jsxDecorator];
export const argTypesEnhancers: ArgTypesEnhancer<ReactRenderer>[] = [enhanceArgTypes];
export { applyDecorators } from './docs/applyDecorators';

View File

@ -0,0 +1,2 @@
export const parameters: {} = { renderer: 'react' };
export { render, renderToCanvas } from './render';

View File

@ -1,5 +1,18 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const addons: StorybookConfig['addons'] = [
require.resolve('@storybook/react-dom-shim/dist/preset'),
];
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsConfig = await options.presets.apply('docs', {}, options);
const docsEnabled = Object.keys(docsConfig).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
@ -17,9 +17,12 @@ export const LoggedOut = {};
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import { Page } from './Page';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -26,16 +26,8 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": {
"types": "./dist/preset.d.ts",
"require": "./dist/preset.js",
"import": "./dist/preset.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -76,8 +68,8 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts",
"./src/preset.ts"
"./src/preset.ts",
"./src/entry-preview.ts"
],
"platform": "browser"
},

View File

@ -1 +0,0 @@
export * from './dist/config';

View File

@ -2,6 +2,8 @@ import fs from 'fs-extra';
import yaml from 'yaml';
import type { StorybookConfig, Tag, StoryName, ComponentTitle } from '@storybook/types';
import { join } from 'path';
type FileContent = {
title: ComponentTitle;
tags?: Tag[];
@ -34,3 +36,13 @@ export const experimental_indexers: StorybookConfig['experimental_indexers'] = (
},
...(existingIndexers || []),
];
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const { presetsList } = options;
if (!presetsList) {
return input;
}
const result: string[] = [];
return result.concat(input).concat([join(__dirname, 'entry-preview.mjs')]);
};

View File

@ -26,11 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json",
"./templates/HOC.svelte": "./templates/HOC.svelte",
"./templates/PreviewRender.svelte": "./templates/PreviewRender.svelte",
@ -80,7 +78,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config.mjs';

View File

@ -1,7 +0,0 @@
import { parameters as docsParams } from './docs/config';
export const parameters: {} = { renderer: 'svelte' as const, ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorators';

View File

@ -1,17 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './extractArgTypes';
import { extractComponentDescription } from './extractComponentDescription';
import { sourceDecorator } from './sourceDecorator';
export const parameters: {} = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: Addon_DecoratorFunction<unknown>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -1,16 +1,17 @@
/* eslint-disable no-underscore-dangle */
import { addons, useEffect } from '@storybook/preview-api';
import { deprecate } from '@storybook/client-logger';
import type { ArgTypes, Args, StoryContext, Renderer } from '@storybook/types';
import type { ArgTypes, Args, StoryContext } from '@storybook/types';
import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools';
import type { SvelteRenderer } from '../types';
/**
* Check if the sourcecode should be generated.
* Check if the source-code should be generated.
*
* @param context StoryContext
*/
const skipSourceRender = (context: StoryContext<Renderer>) => {
const skipSourceRender = (context: StoryContext<SvelteRenderer>) => {
const sourceParams = context?.parameters.docs?.source;
const isArgsStory = context?.parameters.__isArgsStory;
@ -162,7 +163,7 @@ function getWrapperProperties(component: any) {
* @param storyFn Fn
* @param context StoryContext
*/
export const sourceDecorator = (storyFn: any, context: StoryContext<Renderer>) => {
export const sourceDecorator = (storyFn: any, context: StoryContext<SvelteRenderer>) => {
const channel = addons.getChannel();
const skip = skipSourceRender(context);
const story = storyFn();

View File

@ -0,0 +1,18 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './docs/extractArgTypes';
import { extractComponentDescription } from './docs/extractComponentDescription';
import { sourceDecorator } from './docs/sourceDecorator';
import type { SvelteRenderer } from './types';
export const parameters = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: DecoratorFunction<SvelteRenderer>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer<SvelteRenderer>[] = [enhanceArgTypes];

View File

@ -0,0 +1,4 @@
export const parameters: {} = { renderer: 'svelte' };
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorators';

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import Page from './Page.svelte';
@ -17,9 +17,12 @@ export const LoggedOut = {};
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/svelte';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import Page from './Page.svelte';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/svelte';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import Page from './Page.svelte';
@ -21,9 +21,12 @@ export const LoggedOut: Story = {};
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -26,11 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -82,7 +80,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config';

View File

@ -1,7 +0,0 @@
import { parameters as docsParams } from './docs/config';
export const parameters: {} = { renderer: 'vue' as const, ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorateStory';

View File

@ -1,16 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './extractArgTypes';
import { sourceDecorator } from './sourceDecorator';
export const parameters: {} = {
docs: {
story: { inline: true, iframeHeight: '120px' },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: Addon_DecoratorFunction<any>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -0,0 +1,17 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './docs/extractArgTypes';
import { sourceDecorator } from './docs/sourceDecorator';
import type { VueRenderer } from './types';
export const parameters = {
docs: {
story: { inline: true, iframeHeight: '120px' },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: DecoratorFunction<VueRenderer>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer<VueRenderer>[] = [enhanceArgTypes];

View File

@ -0,0 +1,3 @@
export const parameters: {} = { renderer: 'vue' };
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorateStory';

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import MyPage from './Page.vue';
export default {
@ -19,9 +19,12 @@ export const LoggedOut = {};
export const LoggedIn = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -26,11 +26,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -81,7 +79,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config.mjs';

View File

@ -1,7 +0,0 @@
import { parameters as docsParams } from './docs/config';
export const parameters: {} = { renderer: 'vue3' as const, ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorateStory';

View File

@ -1,16 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './extractArgTypes';
import { sourceDecorator } from './sourceDecorator';
export const parameters: {} = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: Addon_DecoratorFunction<unknown>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -1,7 +1,7 @@
/* eslint-disable no-eval */
/* eslint-disable no-underscore-dangle */
import { addons } from '@storybook/preview-api';
import type { ArgTypes, Args, StoryContext, Renderer } from '@storybook/types';
import type { ArgTypes, Args, StoryContext } from '@storybook/types';
import { SourceType, SNIPPET_RENDERED } from '@storybook/docs-tools';
@ -25,13 +25,14 @@ import {
replaceValueWithRef,
generateExpression,
} from './utils';
import type { VueRenderer } from '../types';
/**
* Check if the sourcecode should be generated.
*
* @param context StoryContext
*/
const skipSourceRender = (context: StoryContext<Renderer>) => {
const skipSourceRender = (context: StoryContext<VueRenderer>) => {
const sourceParams = context?.parameters.docs?.source;
const isArgsStory = context?.parameters.__isArgsStory;
const isDocsViewMode = context?.viewMode === 'docs';
@ -153,7 +154,7 @@ function generateScriptSetup(args: Args, argTypes: ArgTypes, components: any[]):
*/
function getTemplateComponents(
renderFn: any,
context?: StoryContext<Renderer>
context?: StoryContext<VueRenderer>
): (TemplateChildNode | VNode)[] {
try {
const originalStoryFn = renderFn;
@ -274,7 +275,7 @@ export function generateTemplateSource(
* @param storyFn Fn
* @param context StoryContext
*/
export const sourceDecorator = (storyFn: any, context: StoryContext<Renderer>) => {
export const sourceDecorator = (storyFn: any, context: StoryContext<VueRenderer>) => {
const skip = skipSourceRender(context);
const story = storyFn();
@ -290,7 +291,7 @@ export const sourceDecorator = (storyFn: any, context: StoryContext<Renderer>) =
return story;
};
export function generateSource(context: StoryContext<Renderer>) {
export function generateSource(context: StoryContext<VueRenderer>) {
const channel = addons.getChannel();
const { args = {}, argTypes = {}, id } = context || {};
const storyComponents = getTemplateComponents(context?.originalStoryFn, context);

View File

@ -0,0 +1,17 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { extractComponentDescription, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes } from './docs/extractArgTypes';
import { sourceDecorator } from './docs/sourceDecorator';
import type { VueRenderer } from './types';
export const parameters = {
docs: {
story: { inline: true },
extractArgTypes,
extractComponentDescription,
},
};
export const decorators: DecoratorFunction<VueRenderer>[] = [sourceDecorator];
export const argTypesEnhancers: ArgTypesEnhancer<VueRenderer>[] = [enhanceArgTypes];

View File

@ -0,0 +1,3 @@
export const parameters: {} = { renderer: 'vue3' };
export { render, renderToCanvas } from './render';
export { decorateStory as applyDecorators } from './decorateStory';

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -1,4 +1,4 @@
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import MyPage from './Page.vue';
export default {
@ -22,9 +22,12 @@ export const LoggedIn = {
}),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/vue3';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import MyPage from './Page.vue';
const meta: Meta<typeof MyPage> = {
@ -24,10 +24,13 @@ type Story = StoryObj<typeof MyPage>;
export const LoggedIn: Story = {
play: async ({ canvasElement }: any) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/vue3';
import { within, userEvent } from '@storybook/testing-library';
import { within, userEvent, expect } from '@storybook/test';
import MyPage from './Page.vue';
const meta = {
@ -24,10 +24,13 @@ type Story = StoryObj<typeof meta>;
export const LoggedIn: Story = {
play: async ({ canvasElement }: any) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
const loginButton = canvas.getByRole('button', { name: /Log in/i });
await expect(loginButton).toBeInTheDocument();
await userEvent.click(loginButton);
await expect(loginButton).not.toBeInTheDocument();
const logoutButton = canvas.getByRole('button', { name: /Log out/i });
await expect(logoutButton).toBeInTheDocument();
},
};

View File

@ -29,11 +29,9 @@
"require": "./dist/index.js",
"import": "./dist/index.mjs"
},
"./preview": {
"types": "./dist/config.d.ts",
"require": "./dist/config.js",
"import": "./dist/config.mjs"
},
"./preset": "./preset.js",
"./dist/entry-preview.mjs": "./dist/entry-preview.mjs",
"./dist/entry-preview-docs.mjs": "./dist/entry-preview-docs.mjs",
"./package.json": "./package.json"
},
"main": "dist/index.js",
@ -81,7 +79,9 @@
"bundler": {
"entries": [
"./src/index.ts",
"./src/config.ts"
"./src/preset.ts",
"./src/entry-preview.ts",
"./src/entry-preview-docs.ts"
],
"platform": "browser"
},

View File

@ -0,0 +1 @@
module.exports = require('./dist/preset');

View File

@ -1 +0,0 @@
export * from './dist/config';

View File

@ -1,5 +0,0 @@
import { parameters as docsParams } from './docs/config';
export const parameters: {} = { renderer: 'web-components' as const, ...docsParams };
export { decorators, argTypesEnhancers } from './docs/config';
export { render, renderToCanvas } from './render';

View File

@ -1,21 +0,0 @@
import type { Addon_DecoratorFunction, ArgTypesEnhancer } from '@storybook/types';
import { SourceType, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes, extractComponentDescription } from './custom-elements';
import { sourceDecorator } from './sourceDecorator';
import type { StoryFnHtmlReturnType } from '../types';
export const decorators: Addon_DecoratorFunction<StoryFnHtmlReturnType>[] = [sourceDecorator];
export const parameters: object = {
docs: {
extractArgTypes,
extractComponentDescription,
story: { inline: true },
source: {
type: SourceType.DYNAMIC,
language: 'html',
},
},
};
export const argTypesEnhancers: ArgTypesEnhancer[] = [enhanceArgTypes];

View File

@ -0,0 +1,21 @@
import type { ArgTypesEnhancer, DecoratorFunction } from '@storybook/types';
import { SourceType, enhanceArgTypes } from '@storybook/docs-tools';
import { extractArgTypes, extractComponentDescription } from './docs/custom-elements';
import { sourceDecorator } from './docs/sourceDecorator';
import type { WebComponentsRenderer } from './types';
export const decorators: DecoratorFunction<WebComponentsRenderer>[] = [sourceDecorator];
export const parameters = {
docs: {
extractArgTypes,
extractComponentDescription,
story: { inline: true },
source: {
type: SourceType.DYNAMIC,
language: 'html',
},
},
};
export const argTypesEnhancers: ArgTypesEnhancer<WebComponentsRenderer>[] = [enhanceArgTypes];

View File

@ -0,0 +1,2 @@
export const parameters: {} = { renderer: 'web-components' };
export { render, renderToCanvas } from './render';

View File

@ -0,0 +1,12 @@
import type { StorybookConfig } from '@storybook/types';
import { join } from 'path';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = async (input, options) => {
const docsEnabled = Object.keys(await options.presets.apply('docs', {}, options)).length > 0;
const result: string[] = [];
return result
.concat(input)
.concat([join(__dirname, 'entry-preview.mjs')])
.concat(docsEnabled ? [join(__dirname, 'entry-preview-docs.mjs')] : []);
};

View File

@ -10556,7 +10556,7 @@ __metadata:
languageName: node
linkType: hard
"aria-query@npm:^5.0.0, aria-query@npm:^5.1.3, aria-query@npm:^5.3.0":
"aria-query@npm:^5.1.3, aria-query@npm:^5.3.0":
version: 5.3.0
resolution: "aria-query@npm:5.3.0"
dependencies:

View File

@ -162,6 +162,6 @@ When Storybook generates the titles for all matching stories, they'll retain the
### Story Indexers
[Story Indexers](./main-config-indexers.md) are a set of heuristics used by Storybook to crawl your filesystem based on a given glob pattern searching for matching stories, which is then used to generate an `index.json` (formerly `stories.json`) file responsible for populating the sidebar with the necessary information. By default, this heuristic will look for files that contain the following scheme `*.stories.@(js|jsx|mjs|ts|tsx)`.
[Story Indexers](../api/main-config-indexers.md) are a set of heuristics used by Storybook to crawl your filesystem based on a given glob pattern searching for matching stories, which is then used to generate an `index.json` (formerly `stories.json`) file responsible for populating the sidebar with the necessary information. By default, this heuristic will look for files that contain the following scheme `*.stories.@(js|jsx|mjs|ts|tsx)`.
You can provide your own indexer to include stories with a different naming convention, adjust the automatic title generation beyond a prefix, and many other use cases. For more information, see the [Story Indexers API reference](./main-config-indexers.md).
You can provide your own indexer to include stories with a different naming convention, adjust the automatic title generation beyond a prefix, and many other use cases. For more information, see the [Story Indexers API reference](../api/main-config-indexers.md).