Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactions: Fix deeply nested nodes in the panel debugger #23108

Merged
merged 9 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions code/addons/interactions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
},
"devDependencies": {
"@devtools-ds/object-inspector": "^1.1.2",
"@storybook/jest": "future",
"@storybook/testing-library": "future",
"@storybook/jest": "next",
"@storybook/testing-library": "next",
"@types/node": "^16.0.0",
"formik": "^2.2.9",
"typescript": "~4.9.3"
Expand Down
13 changes: 11 additions & 2 deletions code/addons/interactions/src/components/MethodCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,14 @@ export const Node = ({
/* eslint-enable no-underscore-dangle */

case Object.prototype.toString.call(value) === '[object Object]':
return <ObjectNode value={value} showInspector={showObjectInspector} {...props} />;
return (
<ObjectNode
value={value}
showInspector={showObjectInspector}
callsById={callsById}
{...props}
/>
);
default:
return <OtherNode value={value} {...props} />;
}
Expand Down Expand Up @@ -222,11 +229,13 @@ export const ArrayNode = ({
export const ObjectNode = ({
showInspector,
value,
callsById,
nested = false,
}: {
showInspector?: boolean;
value: object;
nested?: boolean;
callsById?: Map<Call['id'], Call>;
}) => {
const isDarkMode = useTheme().base === 'dark';
const colors = useThemeColors();
Expand All @@ -253,7 +262,7 @@ export const ObjectNode = ({
.map(([k, v]) => (
<Fragment key={k}>
<span style={{ color: colors.objectkey }}>{k}: </span>
<Node value={v} nested />
<Node value={v} callsById={callsById} nested />
</Fragment>
)),
<span>, </span>
Expand Down
32 changes: 28 additions & 4 deletions code/addons/interactions/template/stories/basics.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ export const Step = {
export const TypeAndClear = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
// TODO: seems like userEvent.type + userEvent.clear + userEvent.type is not working for Svelte and Vue2/3. We should probably investigate, might be a bug in userEvent or in our implementation.
await fireEvent.input(canvas.getByTestId('value'), { target: { value: 'initial value' } });
await fireEvent.input(canvas.getByTestId('value'), { target: { value: '' } });
await fireEvent.input(canvas.getByTestId('value'), { target: { value: 'final value' } });
await userEvent.type(canvas.getByTestId('value'), 'initial value');
await userEvent.clear(canvas.getByTestId('value'));
await userEvent.type(canvas.getByTestId('value'), 'final value');
},
};

Expand Down Expand Up @@ -96,3 +95,28 @@ export const Validation = {
await expect(args.onSuccess).not.toHaveBeenCalled();
},
};

export const UserEventSetup = {
play: async (context) => {
const { args, canvasElement, step } = context;
const user = userEvent.setup();
const canvas = within(canvasElement);
await step('Select, type and paste on input using user-event v14 setup', async () => {
const input = await canvas.getByRole('textbox');
await user.click(input);
await user.type(input, 'Pasting: ');
await user.paste('foobar');
});
await step('Tab and press enter on submit button', async () => {
await user.pointer([
{ keys: '[TouchA>]', target: await canvas.getByRole('textbox') },
{ keys: '[/TouchA]' },
]);
await user.tab();
await user.keyboard('{enter}');
const submitButton = await canvas.findByRole('button');
await expect(submitButton).toHaveFocus();
await expect(args.onSuccess).toHaveBeenCalled();
});
},
};
10 changes: 7 additions & 3 deletions code/e2e-tests/addon-interactions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ test.describe('addon-interactions', () => {
const panel = sbPage.panelContent();
const runStatusBadge = await panel.locator('[aria-label="Status of the test run"]');
await expect(runStatusBadge).toContainText(/Pass/);
await expect(panel).toContainText(/value: "initial value"/);
await expect(panel).toContainText(/value: ""/);
await expect(panel).toContainText(/value: "final value"/);
await expect(panel).toContainText(/"initial value"/);
await expect(panel).toContainText(/clear/);
await expect(panel).toContainText(/"final value"/);
await expect(panel).toBeVisible();

// Test interactions debugger - Stepping through works, count is correct and values are as expected
Expand All @@ -94,6 +94,9 @@ test.describe('addon-interactions', () => {
// Test rerun state (from addon panel) - Interactions have rerun, count is correct and values are as expected
const rerunInteractionButton = await panel.locator('[aria-label="Rerun"]');
await rerunInteractionButton.click();

await expect(formInput).toHaveValue('final value');

await interactionsRow.first().isVisible();
await interactionsRow.nth(1).isVisible();
await interactionsRow.nth(2).isVisible();
Expand All @@ -108,5 +111,6 @@ test.describe('addon-interactions', () => {
await interactionsRow.nth(2).isVisible();
await expect(interactionsTab).toContainText(/(3)/);
await expect(interactionsTab).toBeVisible();
await expect(formInput).toHaveValue('final value');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Component, Output, EventEmitter } from '@angular/core';
<form id="interaction-test-form" (submit)="handleSubmit($event)">
<label>
Enter Value
<input type="text" data-testid="value" [value]="value" required />
<input type="text" data-testid="value" [(ngModel)]="value" required />
</label>
<button type="submit">Submit</button>
<p *ngIf="complete">Completed!!</p>
Expand Down
5 changes: 1 addition & 4 deletions code/lib/cli/src/generators/baseGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,7 @@ export async function baseGenerator(

if (hasInteractiveStories(rendererId)) {
addons.push('@storybook/addon-interactions');
addonPackages.push(
'@storybook/addon-interactions',
'@storybook/testing-library@^0.1.1-future.2'
);
addonPackages.push('@storybook/addon-interactions', '@storybook/testing-library@^0.2.0-next.0');
}

const files = await fse.readdir(process.cwd());
Expand Down
4 changes: 2 additions & 2 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
"@storybook/html-vite": "workspace:*",
"@storybook/html-webpack5": "workspace:*",
"@storybook/instrumenter": "workspace:*",
"@storybook/jest": "future",
"@storybook/jest": "next",
"@storybook/linter-config": "^3.1.2",
"@storybook/manager": "workspace:*",
"@storybook/manager-api": "workspace:*",
Expand Down Expand Up @@ -184,7 +184,7 @@
"@storybook/svelte": "workspace:*",
"@storybook/svelte-webpack5": "workspace:*",
"@storybook/telemetry": "workspace:*",
"@storybook/testing-library": "future",
"@storybook/testing-library": "next",
"@storybook/theming": "workspace:*",
"@storybook/types": "workspace:*",
"@storybook/vue": "workspace:*",
Expand Down
14 changes: 8 additions & 6 deletions code/renderers/html/template/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,32 @@
export const Form = ({ onSuccess }) => {
const container = document.createElement('div');

const getInnerHTML = ({ complete }) => `
const getInnerHTML = ({ complete, value }) => `
<form id="interaction-test-form">
<label>
Enter Value
<input type="text" data-testid="value" required />
<input type="text" data-testid="value" value="${value}" required />
</label>
<button type="submit">Submit</button>
${complete ? '<p>Completed!!</p>' : ''}
</form>
`;

container.innerHTML = getInnerHTML({ complete: false });
container.innerHTML = getInnerHTML({ complete: false, value: '' });

const form = container.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault();

const { value } = form.querySelector('input'); // Store the current value

setTimeout(() => {
container.innerHTML = getInnerHTML({ complete: true });
container.innerHTML = getInnerHTML({ complete: true, value });
}, 500);
setTimeout(() => {
container.innerHTML = getInnerHTML({ complete: false });
container.innerHTML = getInnerHTML({ complete: false, value });
}, 1500);
onSuccess(e);
onSuccess(value);
});

return container;
Expand Down
2 changes: 1 addition & 1 deletion code/renderers/preact/template/components/Form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const Form = ({ onSuccess }) => {
data-testid="value"
value={value}
required
onChange={(event) => setValue(event.target.value)}
onInput={(event) => setValue(event.target.value)}
/>
</label>
<button type="submit">Submit</button>
Expand Down
4 changes: 2 additions & 2 deletions code/renderers/svelte/template/components/Form.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
<form id="interaction-test-form" on:submit|preventDefault={handleSubmit}>
<label>
Enter Value
<input type="text" data-testid="value" {value} required on:click={handleClick} />
<input type="text" data-testid="value" bind:value required on:click={handleClick} />
</label>
<button type="submit">Submit</button>
{#if complete}<p>Completed!!</p>{/if}
</form>
</form>
11 changes: 7 additions & 4 deletions code/renderers/vue/template/components/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
<form id="interaction-test-form" @submit.prevent="onSubmit">
<label>
Enter Value
<input type="text" data-testid="value" :value="value" required @click="setValue" />
<input
type="text"
data-testid="value"
:value="value"
@input="value = $event.target.value"
required
/>
</label>
<button type="submit">Submit</button>
<p v-if="complete">Completed!!</p>
Expand All @@ -27,9 +33,6 @@ export default {
},

methods: {
setValue(event) {
this.value = event.target.value;
},
onSubmit() {
this.onSuccess(this.value);
setTimeout(() => {
Expand Down
5 changes: 1 addition & 4 deletions code/renderers/vue3/template/components/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<form id="interaction-test-form" @submit.prevent="onSubmit">
<label>
Enter Value
<input type="text" data-testid="value" :value="value" required @click="setValue" />
<input type="text" data-testid="value" v-model="value" required />
</label>
<button type="submit">Submit</button>
<p v-if="complete">Completed!!</p>
Expand All @@ -27,9 +27,6 @@ export default {
},

methods: {
setValue(event) {
this.value = event.target.value;
},
onSubmit() {
this.onSuccess(this.value);
setTimeout(() => {
Expand Down
Loading