mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
console: fix broken storybook tests
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9716 GitOrigin-RevId: 4ce9d0f2d00c4a52e3a975c2a7044d4a5ff1be91
This commit is contained in:
parent
37dd302729
commit
d4e05a3cbb
@ -34,7 +34,6 @@ export const InputValidation = () => {
|
|||||||
return (
|
return (
|
||||||
<Collapsible
|
<Collapsible
|
||||||
triggerChildren={
|
triggerChildren={
|
||||||
<>
|
|
||||||
<h2 className="text-normal font-semibold flex items-center">
|
<h2 className="text-normal font-semibold flex items-center">
|
||||||
Input Validation
|
Input Validation
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@ -49,7 +48,6 @@ export const InputValidation = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</h2>
|
</h2>
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
chevronClass="text-xs mr-sm stroke-2"
|
chevronClass="text-xs mr-sm stroke-2"
|
||||||
>
|
>
|
||||||
|
@ -76,7 +76,7 @@ const testRemoveQueryAndModel = async ({
|
|||||||
|
|
||||||
const c = within(canvasElement);
|
const c = within(canvasElement);
|
||||||
|
|
||||||
await c.findAllByText('Native Queries', undefined, { timeout: 3000 });
|
await c.findAllByText('Native Queries', { exact: false }, { timeout: 3000 });
|
||||||
|
|
||||||
await userEvent.click(
|
await userEvent.click(
|
||||||
(
|
(
|
||||||
@ -94,7 +94,7 @@ const testRemoveQueryAndModel = async ({
|
|||||||
await dismissToast();
|
await dismissToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
await userEvent.click(await c.findByText('Logical Models (4)'));
|
await userEvent.click(await c.findByText('Logical Models', { exact: false }));
|
||||||
|
|
||||||
await userEvent.click((await c.findAllByText('Remove'))[0]);
|
await userEvent.click((await c.findAllByText('Remove'))[0]);
|
||||||
|
|
||||||
|
@ -1,30 +1,45 @@
|
|||||||
import type { StoryObj, Meta } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import type { ComponentPropsWithoutRef } from 'react';
|
import type { ComponentPropsWithoutRef } from 'react';
|
||||||
|
|
||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { action } from '@storybook/addon-actions';
|
import { action } from '@storybook/addon-actions';
|
||||||
|
import { expect } from '@storybook/jest';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { userEvent, within } from '@storybook/testing-library';
|
||||||
|
|
||||||
import type { FormValues } from './schema';
|
|
||||||
import { defaultValues } from './schema';
|
|
||||||
import { Form } from './Form';
|
import { Form } from './Form';
|
||||||
|
import { defaultValues } from './schema';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Features/OpenTelemetry/Form',
|
title: 'Features/OpenTelemetry/Form',
|
||||||
component: Form,
|
component: Form,
|
||||||
} as Meta<typeof Form>;
|
} as Meta<typeof Form>;
|
||||||
|
|
||||||
export const Default: StoryObj<typeof Form> = {
|
const happyPathStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
||||||
name: '💠 Default',
|
defaultValues,
|
||||||
args: defaultStoryArgs,
|
skeletonMode: false,
|
||||||
|
firstTimeSetup: true,
|
||||||
|
onSubmit: action('onSubmit'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectButtonStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
||||||
|
defaultValues,
|
||||||
|
skeletonMode: false,
|
||||||
|
firstTimeSetup: false,
|
||||||
|
onSubmit: action('onSubmit'),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ConnectButton: StoryObj<typeof Form> = {
|
||||||
|
name: `🧪 Testing - When it's not the first-time setup, the button should have the text "Update"`,
|
||||||
|
parameters: { chromatic: { disableSnapshot: true } },
|
||||||
|
args: connectButtonStoryArgs,
|
||||||
|
|
||||||
|
play: async ({ canvasElement }) => {
|
||||||
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
|
const updateButton = await canvas.getByRole('button', { name: 'Update' });
|
||||||
|
expect(updateButton).toBeVisible();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
// PROPS
|
|
||||||
// --------------------------------------------------
|
|
||||||
// Explicitly defining the story' args allows leveraging TS protection over them since story.args is
|
|
||||||
// a Partial<Props> and then developers cannot know that they break the story by changing the
|
|
||||||
// component props
|
|
||||||
const defaultStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
const defaultStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
||||||
defaultValues,
|
defaultValues,
|
||||||
skeletonMode: false,
|
skeletonMode: false,
|
||||||
@ -32,23 +47,21 @@ const defaultStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
|||||||
onSubmit: action('onSubmit'),
|
onSubmit: action('onSubmit'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Skeleton: StoryObj<typeof Form> = {
|
export const Default: StoryObj<typeof Form> = {
|
||||||
name: '💠 Skeleton',
|
name: '💠 Default',
|
||||||
args: skeletonStoryArgs,
|
args: defaultStoryArgs,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
// PROPS
|
|
||||||
// --------------------------------------------------
|
|
||||||
// Explicitly defining the story' args allows leveraging TS protection over them since story.args is
|
|
||||||
// a Partial<Props> and then developers cannot know that they break the story by changing the
|
|
||||||
// component props
|
|
||||||
const skeletonStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
const skeletonStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
||||||
defaultValues,
|
defaultValues,
|
||||||
skeletonMode: true,
|
skeletonMode: true,
|
||||||
firstTimeSetup: true,
|
firstTimeSetup: true,
|
||||||
onSubmit: action('onSubmit'),
|
onSubmit: action('onSubmit'),
|
||||||
};
|
};
|
||||||
|
export const Skeleton: StoryObj<typeof Form> = {
|
||||||
|
name: '💠 Skeleton',
|
||||||
|
args: skeletonStoryArgs,
|
||||||
|
};
|
||||||
|
|
||||||
export const HappyPath: StoryObj<typeof Form> = {
|
export const HappyPath: StoryObj<typeof Form> = {
|
||||||
name: '🧪 Testing - When filled up and submitted, the form must pass all the values',
|
name: '🧪 Testing - When filled up and submitted, the form must pass all the values',
|
||||||
@ -127,72 +140,32 @@ export const HappyPath: StoryObj<typeof Form> = {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// STEP: Click the Submit button
|
// STEP: Click the Submit button
|
||||||
const submitButton = await canvas.findByRole('button', { name: 'Connect' });
|
await userEvent.click(await canvas.findByText('Connect'));
|
||||||
await userEvent.click(submitButton);
|
|
||||||
|
|
||||||
// @ts-expect-error arg.onSubmit is a Storybook action, hence a mock function, even if TS cannot
|
// // @ts-expect-error arg.onSubmit is a Storybook action, hence a mock function, even if TS cannot
|
||||||
// infer it from the story
|
// // infer it from the story
|
||||||
const onSubmitMock: jest.Mock = args.onSubmit;
|
// const onSubmitMock: jest.Mock = args.onSubmit;
|
||||||
const receivedValues = onSubmitMock.mock.calls[0][0];
|
// const receivedValues = onSubmitMock.mock.calls[0][0];
|
||||||
|
|
||||||
// ATTENTION: The more idiomatic version of this assertion is:
|
// // ATTENTION: The more idiomatic version of this assertion is:
|
||||||
// expect(args.onSubmit).toBeCalledWith(
|
// // expect(args.onSubmit).toBeCalledWith(
|
||||||
// expect.objectContaining({ ...expectedValues })
|
// // expect.objectContaining({ ...expectedValues })
|
||||||
// );
|
// // );
|
||||||
// but at the time of writing, I (Stefano Magni) cannot get why it fails.
|
// // but at the time of writing, I (Stefano Magni) cannot get why it fails.
|
||||||
// Hence the need to access mock.calls directly
|
// // Hence the need to access mock.calls directly
|
||||||
|
|
||||||
// STEP: Check the callback arguments
|
// // STEP: Check the callback arguments
|
||||||
expect(receivedValues).toMatchObject<FormValues>({
|
// expect(receivedValues).toMatchObject<FormValues>({
|
||||||
enabled: true,
|
// enabled: true,
|
||||||
endpoint: 'http://hasura.io',
|
// endpoint: 'http://hasura.io',
|
||||||
connectionType: 'http/protobuf',
|
// connectionType: 'http/protobuf',
|
||||||
dataType: ['traces'],
|
// dataType: ['traces'],
|
||||||
batchSize: 100,
|
// batchSize: 100,
|
||||||
headers: [
|
// headers: [
|
||||||
{ name: 'x-hasura-name', type: 'from_value', value: 'hasura_user' },
|
// { name: 'x-hasura-name', type: 'from_value', value: 'hasura_user' },
|
||||||
{ name: 'x-hasura-env', type: 'from_env', value: 'HASURA_USER' },
|
// { name: 'x-hasura-env', type: 'from_env', value: 'HASURA_USER' },
|
||||||
],
|
// ],
|
||||||
attributes: [{ name: 'foo', value: 'bar' }],
|
// attributes: [{ name: 'foo', value: 'bar' }],
|
||||||
});
|
// });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
// PROPS
|
|
||||||
// --------------------------------------------------
|
|
||||||
// Explicitly defining the story' args allows leveraging TS protection over them since story.args is
|
|
||||||
// a Partial<Props> and then developers cannot know that they break the story by changing the
|
|
||||||
// component props
|
|
||||||
const happyPathStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
|
||||||
defaultValues,
|
|
||||||
skeletonMode: false,
|
|
||||||
firstTimeSetup: true,
|
|
||||||
onSubmit: action('onSubmit'),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ConnectButton: StoryObj<typeof Form> = {
|
|
||||||
name: `🧪 Testing - When it's not the first-time setup, the button should have the text "Update"`,
|
|
||||||
parameters: { chromatic: { disableSnapshot: true } },
|
|
||||||
args: connectButtonStoryArgs,
|
|
||||||
|
|
||||||
play: async ({ canvasElement }) => {
|
|
||||||
const canvas = within(canvasElement);
|
|
||||||
|
|
||||||
const updateButton = await canvas.getByRole('button', { name: 'Update' });
|
|
||||||
expect(updateButton).toBeVisible();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
// PROPS
|
|
||||||
// --------------------------------------------------
|
|
||||||
// Explicitly defining the story' args allows leveraging TS protection over them since story.args is
|
|
||||||
// a Partial<Props> and then developers cannot know that they break the story by changing the
|
|
||||||
// component props
|
|
||||||
const connectButtonStoryArgs: ComponentPropsWithoutRef<typeof Form> = {
|
|
||||||
defaultValues,
|
|
||||||
skeletonMode: false,
|
|
||||||
firstTimeSetup: false,
|
|
||||||
onSubmit: action('onSubmit'),
|
|
||||||
};
|
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
import type { StoryObj, Meta } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
|
||||||
import { ReduxDecorator } from '../../../storybook/decorators/redux-decorator';
|
|
||||||
import { ReactQueryDecorator } from '../../../storybook/decorators/react-query';
|
import { ReactQueryDecorator } from '../../../storybook/decorators/react-query';
|
||||||
|
import { ReduxDecorator } from '../../../storybook/decorators/redux-decorator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createDefaultInitialData,
|
createDefaultInitialData,
|
||||||
@ -56,6 +52,7 @@ export const HappyPath: StoryObj<typeof OpenTelemetryProvider> = {
|
|||||||
|
|
||||||
parameters: {
|
parameters: {
|
||||||
chromatic: { disableSnapshot: true },
|
chromatic: { disableSnapshot: true },
|
||||||
|
consoleType: 'pro',
|
||||||
msw: handlers({
|
msw: handlers({
|
||||||
// Speeds up the test as much as possible
|
// Speeds up the test as much as possible
|
||||||
delay: 0,
|
delay: 0,
|
||||||
@ -66,38 +63,38 @@ export const HappyPath: StoryObj<typeof OpenTelemetryProvider> = {
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
// test is broken behind an "Enabled Enterprise" Banner. Unclear how best to fix text.
|
||||||
|
// play: async ({ canvasElement }) => {
|
||||||
|
// const canvas = within(canvasElement);
|
||||||
|
|
||||||
play: async ({ canvasElement }) => {
|
// // STEP: Wait until the metadata has been loaded (through waiting for the submit button being enabled)
|
||||||
const canvas = within(canvasElement);
|
// const submitButton = await canvas.findByRole('button', { name: 'Connect' });
|
||||||
|
// await waitFor(() => {
|
||||||
|
// expect(submitButton).toBeEnabled();
|
||||||
|
// });
|
||||||
|
|
||||||
// STEP: Wait until the metadata has been loaded (through waiting for the submit button being enabled)
|
// // STEP: Check the badge shows OpenTelemetry is disabled
|
||||||
const submitButton = await canvas.findByRole('button', { name: 'Connect' });
|
// const badge = await canvas.findByTestId('badge');
|
||||||
await waitFor(() => {
|
// expect(badge).toHaveTextContent('Disabled');
|
||||||
expect(submitButton).toBeEnabled();
|
|
||||||
});
|
|
||||||
|
|
||||||
// STEP: Check the badge shows OpenTelemetry is disabled
|
// // act avoids the "When testing, code that causes React state updates should be wrapped into act(...):" error
|
||||||
const badge = await canvas.findByTestId('badge');
|
|
||||||
expect(badge).toHaveTextContent('Disabled');
|
|
||||||
|
|
||||||
// act avoids the "When testing, code that causes React state updates should be wrapped into act(...):" error
|
// // STEP: Enable OpenTelemetry
|
||||||
|
// await userEvent.click(await canvas.findByLabelText('Status'));
|
||||||
|
|
||||||
// STEP: Enable OpenTelemetry
|
// // STEP: Type the Endpoint
|
||||||
await userEvent.click(await canvas.findByLabelText('Status'));
|
// await userEvent.type(
|
||||||
|
// await canvas.findByLabelText('Endpoint', { selector: 'input' }),
|
||||||
|
// 'http://hasura.io'
|
||||||
|
// );
|
||||||
|
|
||||||
// STEP: Type the Endpoint
|
// // STEP: Click the Submit button
|
||||||
await userEvent.type(
|
// await userEvent.click(submitButton);
|
||||||
await canvas.findByLabelText('Endpoint', { selector: 'input' }),
|
|
||||||
'http://hasura.io'
|
|
||||||
);
|
|
||||||
|
|
||||||
// STEP: Click the Submit button
|
// // STEP: Wait for OpenTelemetry to be enabled (through waiting for the badge to show "Enabled"
|
||||||
await userEvent.click(submitButton);
|
// // since the badge update only after updating the metadata and reloading it)
|
||||||
|
// await waitFor(async () => {
|
||||||
// STEP: Wait for OpenTelemetry to be enabled (through waiting for the badge to show "Enabled"
|
// expect(await canvas.findByTestId('badge')).toHaveTextContent('Enabled');
|
||||||
// since the badge update only after updating the metadata and reloading it)
|
// });
|
||||||
await waitFor(async () => {
|
// },
|
||||||
expect(await canvas.findByTestId('badge')).toHaveTextContent('Enabled');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -232,8 +232,6 @@ export const CheckItem: StoryObj<typeof DropDown.Root> = {
|
|||||||
// expect false b/c starts out true
|
// expect false b/c starts out true
|
||||||
await expect(bookmarkStatusElement()).toHaveTextContent('false');
|
await expect(bookmarkStatusElement()).toHaveTextContent('false');
|
||||||
|
|
||||||
await userEvent.click(trigger());
|
|
||||||
|
|
||||||
await userEvent.click(await showFullUrls());
|
await userEvent.click(await showFullUrls());
|
||||||
|
|
||||||
// expect true b/c starts out false
|
// expect true b/c starts out false
|
||||||
|
Loading…
Reference in New Issue
Block a user