Skip to content

Commit

Permalink
Merge branch 'next' into kasper/fix-attach-spy
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf authored Oct 13, 2023
2 parents 4b3d638 + 995e064 commit 8d51ad7
Show file tree
Hide file tree
Showing 41 changed files with 458 additions and 219 deletions.
10 changes: 5 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -609,30 +609,30 @@ workflows:
requires:
- build
- create-sandboxes:
parallelism: 34
parallelism: 36
requires:
- build
# - smoke-test-sandboxes: # disabled for now
# requires:
# - create-sandboxes
- build-sandboxes:
parallelism: 34
parallelism: 36
requires:
- create-sandboxes
- chromatic-sandboxes:
parallelism: 31
parallelism: 33
requires:
- build-sandboxes
- e2e-production:
parallelism: 31
parallelism: 33
requires:
- build-sandboxes
- e2e-dev:
parallelism: 4
requires:
- create-sandboxes
- test-runner-production:
parallelism: 31
parallelism: 33
requires:
- build-sandboxes
# TODO: reenable once we find out the source of flakyness
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/generate-sandboxes-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ jobs:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
CLEANUP_SANDBOX_NODE_MODULES: true
steps:
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- uses: actions/checkout@v3
with:
ref: main
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: Setup git user
run: |
git config --global user.name "Storybook Bot"
Expand All @@ -43,7 +43,7 @@ jobs:
run: yarn wait-on http://localhost:6001
working-directory: ./code
- name: Generate
run: yarn generate-sandboxes --local-registry --exclude=angular-cli/prerelease
run: yarn generate-sandboxes --local-registry
working-directory: ./code
- name: Publish
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=main
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/generate-sandboxes-next.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ jobs:
YARN_ENABLE_IMMUTABLE_INSTALLS: false
CLEANUP_SANDBOX_NODE_MODULES: true
steps:
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- uses: actions/checkout@v3
with:
ref: next
- uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
- name: Setup git user
run: |
git config --global user.name "Storybook Bot"
Expand All @@ -43,7 +43,7 @@ jobs:
run: yarn wait-on http://localhost:6001
working-directory: ./code
- name: Generate
run: yarn generate-sandboxes --local-registry --exclude=angular-cli/prerelease --debug
run: yarn generate-sandboxes --local-registry --debug
working-directory: ./code
- name: Publish
run: yarn publish-sandboxes --remote=https://storybook-bot:${{ secrets.PAT_STORYBOOK_BOT}}@github.com/storybookjs/sandboxes.git --push --branch=next
Expand Down
2 changes: 1 addition & 1 deletion code/builders/builder-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"peerDependencies": {
"@preact/preset-vite": "*",
"typescript": ">= 4.3.x",
"vite": "^3.0.0 || ^4.0.0",
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0",
"vite-plugin-glimmerx": "*"
},
"peerDependenciesMeta": {
Expand Down
3 changes: 1 addition & 2 deletions code/builders/builder-vite/src/build.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { build as viteBuild, mergeConfig } from 'vite';
import type { Options } from '@storybook/types';
import { commonConfig } from './vite-config';

import { sanitizeEnvVars } from './envs';

export async function build(options: Options) {
const { build: viteBuild, mergeConfig } = await import('vite');
const { presets } = options;

const config = await commonConfig(options, 'build');
Expand All @@ -21,6 +21,5 @@ export async function build(options: Options) {
}).build;

const finalConfig = await presets.apply('viteFinal', config, options);

await viteBuild(await sanitizeEnvVars(options, finalConfig));
}
10 changes: 7 additions & 3 deletions code/builders/builder-vite/src/codegen-entries.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { loadPreviewOrConfigFile } from '@storybook/core-common';
import type { Options } from '@storybook/types';
import slash from 'slash';
import { normalizePath } from 'vite';
import { listStories } from './list-stories';

const absoluteFilesToImport = (files: string[], name: string) =>
const absoluteFilesToImport = async (
files: string[],
name: string,
normalizePath: (id: string) => string
) =>
files
.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`)
.join('\n');

export async function generateVirtualStoryEntryCode(options: Options) {
const { normalizePath } = await import('vite');
const storyEntries = await listStories(options);
const resolveMap = storyEntries.reduce<Record<string, string>>(
(prev, entry) => ({ ...prev, [entry]: entry.replace(slash(process.cwd()), '.') }),
Expand All @@ -18,7 +22,7 @@ export async function generateVirtualStoryEntryCode(options: Options) {
const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');

return `
${absoluteFilesToImport(storyEntries, 'story')}
${await absoluteFilesToImport(storyEntries, 'story', normalizePath)}
function loadable(key) {
return {${modules}}[key];
Expand Down
3 changes: 2 additions & 1 deletion code/builders/builder-vite/src/codegen-importfn-script.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from 'path';
import { normalizePath } from 'vite';

import type { Options } from '@storybook/types';
import { logger } from '@storybook/node-logger';

Expand All @@ -26,6 +26,7 @@ function toImportPath(relativePath: string) {
* @param stories An array of absolute story paths.
*/
async function toImportFn(stories: string[]) {
const { normalizePath } = await import('vite');
const objectEntries = stories.map((file) => {
const ext = path.extname(file);
const relativePath = normalizePath(path.relative(process.cwd(), file));
Expand Down
3 changes: 2 additions & 1 deletion code/builders/builder-vite/src/list-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { glob } from 'glob';
import { normalizeStories, commonGlobOptions } from '@storybook/core-common';

import type { Options } from '@storybook/types';
import { normalizePath } from 'vite';

export async function listStories(options: Options) {
const { normalizePath } = await import('vite');

return (
await Promise.all(
normalizeStories(await options.presets.apply('stories', [], options), {
Expand Down
2 changes: 1 addition & 1 deletion code/builders/builder-vite/src/optimizeDeps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as path from 'path';
import { normalizePath, resolveConfig } from 'vite';
import type { InlineConfig as ViteInlineConfig, UserConfig } from 'vite';
import type { Options } from '@storybook/types';
import { listStories } from './list-stories';
Expand Down Expand Up @@ -128,6 +127,7 @@ const asyncFilter = async (arr: string[], predicate: (val: string) => Promise<bo

export async function getOptimizeDeps(config: ViteInlineConfig, options: Options) {
const { root = process.cwd() } = config;
const { normalizePath, resolveConfig } = await import('vite');
const absoluteStories = await listStories(options);
const stories = absoluteStories.map((storyPath) => normalizePath(path.relative(root, storyPath)));
// TODO: check if resolveConfig takes a lot of time, possible optimizations here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import findCacheDirectory from 'find-cache-dir';
import { init, parse } from 'es-module-lexer';
import MagicString from 'magic-string';
import { ensureFile, writeFile } from 'fs-extra';
import { mergeAlias } from 'vite';
import type { Alias, Plugin } from 'vite';

const escapeKeys = (key: string) => key.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
Expand Down Expand Up @@ -38,6 +37,8 @@ const replacementMap = new Map([
*/
export async function externalGlobalsPlugin(externals: Record<string, string>) {
await init;
const { mergeAlias } = await import('vite');

return {
name: 'storybook:external-globals-plugin',
enforce: 'post',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
import { parse } from 'es-module-lexer';
import MagicString from 'magic-string';
import { createFilter } from 'vite';

const include = [/\.stories\.([tj])sx?$/, /(stories|story).mdx$/];
const filter = createFilter(include);
export async function injectExportOrderPlugin() {
const { createFilter } = await import('vite');

export const injectExportOrderPlugin = {
name: 'storybook:inject-export-order-plugin',
// This should only run after the typescript has been transpiled
enforce: 'post',
async transform(code: string, id: string) {
if (!filter(id)) return undefined;
const include = [/\.stories\.([tj])sx?$/, /(stories|story).mdx$/];
const filter = createFilter(include);

// TODO: Maybe convert `injectExportOrderPlugin` to function that returns object,
// and run `await init;` once and then call `parse()` without `await`,
// instead of calling `await parse()` every time.
const [, exports] = await parse(code);
return {
name: 'storybook:inject-export-order-plugin',
// This should only run after the typescript has been transpiled
enforce: 'post',
async transform(code: string, id: string) {
if (!filter(id)) return undefined;

if (exports.includes('__namedExportsOrder')) {
// user has defined named exports already
return undefined;
}
const s = new MagicString(code);
const orderedExports = exports.filter((e) => e !== 'default');
s.append(`;export const __namedExportsOrder = ${JSON.stringify(orderedExports)};`);
return {
code: s.toString(),
map: s.generateMap({ hires: true, source: id }),
};
},
};
// TODO: Maybe convert `injectExportOrderPlugin` to function that returns object,
// and run `await init;` once and then call `parse()` without `await`,
// instead of calling `await parse()` every time.
const [, exports] = await parse(code);

if (exports.includes('__namedExportsOrder')) {
// user has defined named exports already
return undefined;
}
const s = new MagicString(code);
const orderedExports = exports.filter((e) => e !== 'default');
s.append(`;export const __namedExportsOrder = ${JSON.stringify(orderedExports)};`);
return {
code: s.toString(),
map: s.generateMap({ hires: true, source: id }),
};
},
};
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type { Plugin } from 'vite';
import { createFilter } from 'vite';
import MagicString from 'magic-string';

/**
* This plugin removes HMR `accept` calls in story files. Stories should not be treated
* as hmr boundaries, but vite has a bug which causes them to be treated as boundaries
* (https://github.com/vitejs/vite/issues/9869).
*/
export function stripStoryHMRBoundary(): Plugin {
export async function stripStoryHMRBoundary(): Promise<Plugin> {
const { createFilter } = await import('vite');

const filter = createFilter(/\.stories\.([tj])sx?$/);
return {
name: 'storybook:strip-hmr-boundary-plugin',
Expand Down
7 changes: 4 additions & 3 deletions code/builders/builder-vite/src/vite-config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as path from 'path';
import { loadConfigFromFile, mergeConfig } from 'vite';
import findCacheDirectory from 'find-cache-dir';
import type {
ConfigEnv,
Expand Down Expand Up @@ -41,6 +40,8 @@ export async function commonConfig(
_type: PluginConfigType
): Promise<ViteInlineConfig> {
const configEnv = _type === 'development' ? configEnvServe : configEnvBuild;
const { loadConfigFromFile, mergeConfig } = await import('vite');

const { viteConfigPath } = await getBuilderOptions<BuilderOptions>(options);

const projectRoot = path.resolve(options.configDir, '..');
Expand Down Expand Up @@ -80,8 +81,8 @@ export async function pluginConfig(options: Options) {
const plugins = [
codeGeneratorPlugin(options),
await csfPlugin(options),
injectExportOrderPlugin,
stripStoryHMRBoundary(),
await injectExportOrderPlugin(),
await stripStoryHMRBoundary(),
{
name: 'storybook:allow-storybook-dir',
enforce: 'post',
Expand Down
2 changes: 1 addition & 1 deletion code/builders/builder-vite/src/vite-server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Server } from 'http';
import { createServer } from 'vite';
import type { Options } from '@storybook/types';
import { commonConfig } from './vite-config';
import { getOptimizeDeps } from './optimizeDeps';
Expand Down Expand Up @@ -29,5 +28,6 @@ export async function createViteServer(options: Options, devServer: Server) {

const finalConfig = await presets.apply('viteFinal', config, options);

const { createServer } = await import('vite');
return createServer(await sanitizeEnvVars(options, finalConfig));
}
40 changes: 40 additions & 0 deletions code/e2e-tests/framework-svelte.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable jest/no-disabled-tests */
import { test, expect } from '@playwright/test';
import process from 'process';
import { SbPage } from './util';

const storybookUrl = process.env.STORYBOOK_URL || 'http://localhost:6006';
const templateName = process.env.STORYBOOK_TEMPLATE_NAME;

test.describe('Svelte', () => {
test.skip(
// eslint-disable-next-line jest/valid-title
!templateName?.includes('svelte'),
'Only run this test on Svelte'
);

test.beforeEach(async ({ page }) => {
await page.goto(storybookUrl);
await new SbPage(page).waitUntilLoaded();
});

test('JS story has auto-generated args table', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('stories/renderers/svelte/js-docs', 'docs');
const root = sbPage.previewRoot();
const argsTable = root.locator('.docblock-argstable');
await expect(argsTable).toContainText('Rounds the button');
});

test('TS story has auto-generated args table', async ({ page }) => {
// eslint-disable-next-line jest/valid-title
test.skip(!templateName?.endsWith('ts') || false, 'Only test TS story in TS templates');
const sbPage = new SbPage(page);

await sbPage.navigateToStory('stories/renderers/svelte/ts-docs', 'docs');
const root = sbPage.previewRoot();
const argsTable = root.locator('.docblock-argstable');
await expect(argsTable).toContainText('Rounds the button');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const TestComponent1 = Component({})(class {});
const TestComponent2 = Component({})(class {});
const StandaloneTestComponent = Component({ standalone: true })(class {});
const TestDirective = Directive({})(class {});
const StandaloneTestDirective = Directive({ standalone: true })(class {});
const TestModuleWithDeclarations = NgModule({ declarations: [TestComponent1] })(class {});
const TestModuleWithImportsAndProviders = NgModule({
imports: [TestModuleWithDeclarations],
Expand Down Expand Up @@ -118,6 +119,20 @@ describe('PropertyExtractor', () => {
StandaloneTestComponent,
]);
});

it('should return standalone directives', () => {
const imports = extractImports(
{
imports: [TestModuleWithImportsAndProviders],
},
StandaloneTestDirective
);
expect(imports).toEqual([
CommonModule,
TestModuleWithImportsAndProviders,
StandaloneTestDirective,
]);
});
});

describe('extractDeclarations', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class PropertyExtractor implements NgModuleMetadata {
const isPipe = decorators.some((d) => this.isDecoratorInstanceOf(d, 'Pipe'));

const isDeclarable = isComponent || isDirective || isPipe;
const isStandalone = isComponent && decorators.some((d) => d.standalone);
const isStandalone = (isComponent || isDirective) && decorators.some((d) => d.standalone);

return { isDeclarable, isStandalone };
};
Expand Down
Loading

0 comments on commit 8d51ad7

Please sign in to comment.