Skip to content

Commit

Permalink
Merge branch 'jeppe/teardown-on-forceremount' into jeppe/rerender-queue
Browse files Browse the repository at this point in the history
  • Loading branch information
JReinhold authored Apr 11, 2024
2 parents 1cca11e + 7297628 commit db09f63
Show file tree
Hide file tree
Showing 100 changed files with 2,256 additions and 476 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ jobs:
at: .
- run:
name: Install dependencies
command: yarn install
command: yarn install --no-immutable
working_directory: test-storybooks/portable-stories-kitchen-sink/<< parameters.directory >>
- run:
name: Run Jest tests
Expand Down
3 changes: 2 additions & 1 deletion code/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ ember-output
!.eslintrc.js
!.eslintrc-markdown.js
!.storybook
lib/core-common/templates/base-preview-head.html
lib/core-common/templates/base-preview-head.html
lib/core-server/src/utils/__search-files-tests__
38 changes: 14 additions & 24 deletions code/addons/actions/src/loaders.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
/* eslint-disable no-underscore-dangle */
import type { LoaderFunction } from '@storybook/types';
import { global } from '@storybook/global';
import type { onMockCall as onMockCallType } from '@storybook/test';
import { action } from './runtime';

export const tinySpyInternalState = Symbol.for('tinyspy:spy');
let subscribed = false;

const attachActionsToFunctionMocks: LoaderFunction = (context) => {
const logActionsWhenMockCalled: LoaderFunction = (context) => {
const {
args,
parameters: { actions },
} = context;
if (actions?.disable) return;

Object.entries(args)
.filter(
([, value]) =>
typeof value === 'function' && '_isMockFunction' in value && value._isMockFunction
)
.forEach(([key, value]) => {
// See this discussion for context:
// https://github.com/vitest-dev/vitest/pull/5352
const previous =
value.getMockImplementation() ??
(tinySpyInternalState in value ? value[tinySpyInternalState]?.getOriginal() : undefined);
if (previous?._actionAttached !== true && previous?.isAction !== true) {
const implementation = (...params: unknown[]) => {
action(key)(...params);
return previous?.(...params);
};
implementation._actionAttached = true;
value.mockImplementation(implementation);
}
});
if (
!subscribed &&
'__STORYBOOK_TEST_ON_MOCK_CALL__' in global &&
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));
subscribed = true;
}
};

export const loaders: LoaderFunction[] = [attachActionsToFunctionMocks];
export const loaders: LoaderFunction[] = [logActionsWhenMockCalled];
24 changes: 24 additions & 0 deletions code/addons/actions/template/stories/spies.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { global as globalThis } from '@storybook/global';
import { spyOn } from '@storybook/test';

export default {
component: globalThis.Components.Button,
loaders() {
spyOn(console, 'log').mockName('console.log');
},
args: {
label: 'Button',
},
parameters: {
chromatic: { disable: true },
},
};

export const ShowSpyOnInActions = {
args: {
onClick: () => {
console.log('first');
console.log('second');
},
},
};
42 changes: 0 additions & 42 deletions code/addons/interactions/src/preview.test.ts

This file was deleted.

53 changes: 1 addition & 52 deletions code/addons/interactions/src/preview.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import type {
ArgsEnhancer,
PlayFunction,
PlayFunctionContext,
Renderer,
StepLabel,
} from '@storybook/types';
import { fn, isMockFunction } from '@storybook/test';
import type { PlayFunction, PlayFunctionContext, StepLabel } from '@storybook/types';
import { instrument } from '@storybook/instrumenter';

export const { step: runStep } = instrument(
Expand All @@ -16,50 +9,6 @@ export const { step: runStep } = instrument(
{ intercept: true }
);

export const traverseArgs = (value: unknown, depth = 0, key?: string): unknown => {
// Make sure to not get in infinite loops with self referencing args
if (depth > 5) return value;
if (value == null) return value;
if (isMockFunction(value)) {
// Makes sure we get the arg name in the interactions panel
if (key) value.mockName(key);
return value;
}

// wrap explicit actions in a spy
if (
typeof value === 'function' &&
'isAction' in value &&
value.isAction &&
!('implicit' in value && value.implicit)
) {
const mock = fn(value as any);
if (key) mock.mockName(key);
return mock;
}

if (Array.isArray(value)) {
depth++;
return value.map((item) => traverseArgs(item, depth));
}

if (typeof value === 'object' && value.constructor === Object) {
depth++;
for (const [k, v] of Object.entries(value)) {
if (Object.getOwnPropertyDescriptor(value, k).writable) {
// We have to mutate the original object for this to survive HMR.
(value as Record<string, unknown>)[k] = traverseArgs(v, depth, k);
}
}
return value;
}
return value;
};

const wrapActionsInSpyFns: ArgsEnhancer<Renderer> = ({ initialArgs }) => traverseArgs(initialArgs);

export const argsEnhancers = [wrapActionsInSpyFns];

export const parameters = {
throwPlayFunctionExceptions: false,
};
22 changes: 22 additions & 0 deletions code/e2e-tests/addon-actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,26 @@ test.describe('addon-actions', () => {
});
await expect(logItem).toBeVisible();
});

test('should show spies', async ({ page }) => {
test.skip(
templateName.includes('svelte') && templateName.includes('prerelease'),
'Svelte 5 prerelase does not support automatic actions with our current example components yet'
);
await page.goto(storybookUrl);
const sbPage = new SbPage(page);
sbPage.waitUntilLoaded();

await sbPage.navigateToStory('addons/actions/spies', 'show-spy-on-in-actions');

const root = sbPage.previewRoot();
const button = root.locator('button', { hasText: 'Button' });
await button.click();

await sbPage.viewAddonPanel('Actions');
const logItem = await page.locator('#storybook-panel-root #panel-tab-content', {
hasText: 'console.log',
});
await expect(logItem).toBeVisible();
});
});
4 changes: 2 additions & 2 deletions code/e2e-tests/framework-nextjs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test.describe('Next.js', () => {

await sbPage.viewAddonPanel('Actions');
const logItem = await page.locator('#storybook-panel-root #panel-tab-content', {
hasText: `nextNavigation.${action}`,
hasText: `useRouter().${action}`,
});
await expect(logItem).toBeVisible();
});
Expand Down Expand Up @@ -91,7 +91,7 @@ test.describe('Next.js', () => {

await sbPage.viewAddonPanel('Actions');
const logItem = await page.locator('#storybook-panel-root #panel-tab-content', {
hasText: `nextRouter.${action}`,
hasText: `useRouter().${action}`,
});
await expect(logItem).toBeVisible();
});
Expand Down
29 changes: 28 additions & 1 deletion code/frameworks/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@
"require": "./dist/next-image-loader-stub.js",
"import": "./dist/next-image-loader-stub.mjs"
},
"./headers.mock": {
"types": "./dist/headers/index.d.ts",
"require": "./dist/headers/index.js",
"import": "./dist/headers/index.mjs"
},
"./router.mock": {
"types": "./dist/routing/router/index.d.ts",
"require": "./dist/routing/router/index.js",
"import": "./dist/routing/router/index.mjs"
},
"./navigation.mock": {
"types": "./dist/routing/navigation/index.d.ts",
"require": "./dist/routing/navigation/index.js",
"import": "./dist/routing/navigation/index.mjs"
},
"./package.json": "./package.json"
},
"main": "dist/index.js",
Expand All @@ -59,6 +74,15 @@
],
"dist/image-context": [
"dist/image-context.d.ts"
],
"headers.mock": [
"dist/headers/index.d.ts"
],
"router.mock": [
"dist/routing/router/index.d.ts"
],
"navigation.mock": [
"dist/routing/navigation/index.d.ts"
]
}
},
Expand Down Expand Up @@ -89,14 +113,14 @@
"@babel/preset-typescript": "^7.23.2",
"@babel/runtime": "^7.23.2",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
"@storybook/addon-actions": "workspace:*",
"@storybook/builder-webpack5": "workspace:*",
"@storybook/core-common": "workspace:*",
"@storybook/core-events": "workspace:*",
"@storybook/node-logger": "workspace:*",
"@storybook/preset-react-webpack": "workspace:*",
"@storybook/preview-api": "workspace:*",
"@storybook/react": "workspace:*",
"@storybook/test": "workspace:*",
"@storybook/types": "workspace:*",
"@types/node": "^18.0.0",
"@types/semver": "^7.3.4",
Expand Down Expand Up @@ -157,7 +181,10 @@
"./src/image-context.ts",
"./src/index.ts",
"./src/preset.ts",
"./src/headers/index.ts",
"./src/preview.tsx",
"./src/routing/router/index.ts",
"./src/routing/navigation/index.ts",
"./src/next-image-loader-stub.ts",
"./src/images/decorator.tsx",
"./src/images/next-legacy-image.tsx",
Expand Down
Loading

0 comments on commit db09f63

Please sign in to comment.