From ad6437987612dcf7db166ba274f5f583be0a1a35 Mon Sep 17 00:00:00 2001 From: Vijay Prasanna Date: Tue, 18 Jul 2023 09:57:22 +0530 Subject: [PATCH] console (tests): interaction tests for Native Query relationships PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9831 Co-authored-by: Matthew Goodwin <49927862+m4ttheweric@users.noreply.github.com> GitOrigin-RevId: cf488f5cc20ab77156f1e0c70ba830c3d5b6f495 --- .../ListNativeQueryRelationships.stories.tsx | 161 +++++++++++++++--- .../ListNativeQueryRelationships.tsx | 5 +- .../NativeQueryRelationshipWidget.stories.tsx | 120 +++++++++++++ .../TrackNativeQueryRelationshipForm.tsx | 3 + .../mocks/handlers.ts | 16 ++ .../mocks/mockData.ts | 135 +++++++++++++++ .../components/CardedTableFromReactTable.tsx | 30 +++- .../Data/LogicalModels/mocks/metadata.ts | 4 +- 8 files changed, 443 insertions(+), 31 deletions(-) create mode 100644 frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/NativeQueryRelationshipWidget.stories.tsx create mode 100644 frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/mocks/handlers.ts create mode 100644 frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/mocks/mockData.ts diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.stories.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.stories.tsx index a24ada7c8f1..ecbbe78e56f 100644 --- a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.stories.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.stories.tsx @@ -1,34 +1,157 @@ import { StoryObj, Meta } from '@storybook/react'; import { ReactQueryDecorator } from '../../../../../storybook/decorators/react-query'; -import { ListNativeQueryRelationships } from './ListNativeQueryRelationships'; +import { + ListNativeQueryRelationships, + ListNativeQueryRow, +} from './ListNativeQueryRelationships'; import { ReduxDecorator } from '../../../../../storybook/decorators/redux-decorator'; -import { nativeQueryHandlers } from '../../AddNativeQuery/mocks'; +import { handlers } from '../mocks/handlers'; +import globals from '../../../../../Globals'; +import { userEvent, within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; +import { useState } from 'react'; export default { component: ListNativeQueryRelationships, decorators: [ ReactQueryDecorator(), ReduxDecorator({ - tables: {}, + tables: { + dataHeaders: { + 'x-hasura-admin-secret': globals.adminSecret as any, + }, + }, }), ], - parameters: { - msw: nativeQueryHandlers({ - metadataOptions: { postgres: { models: true, queries: true } }, - trackNativeQueryResult: 'success', - }), - layout: 'fullscreen', - }, - argTypes: { - onDeleteRow: { action: 'clicked delete' }, - onEditRow: { action: 'clicked edit' }, - }, } as Meta; -export const DefaultView: StoryObj = { - args: { - dataSourceName: 'postgres', - nativeQueryName: 'customer_native_query', +export const Basic: StoryObj = { + render: () => ( + + ), + parameters: { + msw: handlers(), + }, +}; + +export const TestBasicFlow: StoryObj = { + render: () => { + const [result, updateResult] = useState(); + + return ( +
+ updateResult(data)} + onDeleteRow={data => updateResult(data)} + /> +
{JSON.stringify(result)}
+
+ ); + }, + parameters: { + msw: handlers(), + }, + name: '🧪 Basic render and edit/delete action', + + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const nativeQueryRelationshipsTable = await canvas.findByTestId( + 'native-query-relationships' + ); + + await expect(nativeQueryRelationshipsTable).toBeInTheDocument(); + + /** + * Check if both header and body have rendered + */ + await expect(nativeQueryRelationshipsTable.children.length).toEqual(2); + + const rows = await canvas.findAllByTestId( + /^native-query-relationships-row-.*$/ + ); + /** + * There should be two rows + */ + await expect(rows.length).toEqual(2); + let rowValues = await canvas.findAllByTestId( + /^native-query-relationships-cell-0-*.*$/ + ); + + /** + * Verify the row values + */ + await expect(rowValues[0]).toHaveTextContent('articles'); + await expect(rowValues[1]).toHaveTextContent('array'); + + let editButton = await within(rowValues[2]).findByTestId('edit-button'); + await userEvent.click(editButton); + + await expect(await canvas.getByTestId('result')).toHaveTextContent( + JSON.stringify({ + name: 'articles', + using: { + column_mapping: { id: 'author_id' }, + insertion_order: null, + remote_native_query: 'get_article', + }, + type: 'array', + }) + ); + + let deleteBtn = await within(rowValues[2]).findByTestId('delete-button'); + await userEvent.click(deleteBtn); + await expect(await canvas.getByTestId('result')).toHaveTextContent( + JSON.stringify({ + name: 'articles', + using: { + column_mapping: { id: 'author_id' }, + insertion_order: null, + remote_native_query: 'get_article', + }, + type: 'array', + }) + ); + + rowValues = await canvas.findAllByTestId( + /^native-query-relationships-cell-1-*.*$/ + ); + + await expect(rowValues[0]).toHaveTextContent('author_details'); + await expect(rowValues[1]).toHaveTextContent('object'); + + editButton = await within(rowValues[2]).findByTestId('edit-button'); + await userEvent.click(editButton); + + await expect(await canvas.getByTestId('result')).toHaveTextContent( + JSON.stringify({ + name: 'author_details', + using: { + column_mapping: { id: 'author_id' }, + insertion_order: null, + remote_native_query: 'get_author_details', + }, + type: 'object', + }) + ); + + deleteBtn = await within(rowValues[2]).findByTestId('delete-button'); + await userEvent.click(deleteBtn); + await expect(await canvas.getByTestId('result')).toHaveTextContent( + JSON.stringify({ + name: 'author_details', + using: { + column_mapping: { id: 'author_id' }, + insertion_order: null, + remote_native_query: 'get_author_details', + }, + type: 'object', + }) + ); }, - render: args => , }; diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.tsx index ae2d4e51598..6b11431fdd3 100644 --- a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/ListNativeQueryRelationships.tsx @@ -75,6 +75,7 @@ export const ListNativeQueryRelationships = ( onClick={() => { onEditRow?.(row.original); }} + data-testid="edit-button" > Edit @@ -84,6 +85,7 @@ export const ListNativeQueryRelationships = ( onClick={() => { onDeleteRow?.(row.original); }} + data-testid="delete-button" > Delete @@ -104,13 +106,14 @@ export const ListNativeQueryRelationships = ( const NativeQueryRelationshipsTable = useCardedTableFromReactTableWithRef(); - if (isLoading) return ; + if (isLoading) return ; return ( ); }; diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/NativeQueryRelationshipWidget.stories.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/NativeQueryRelationshipWidget.stories.tsx new file mode 100644 index 00000000000..d15986ab745 --- /dev/null +++ b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/NativeQueryRelationshipWidget.stories.tsx @@ -0,0 +1,120 @@ +import { Meta, StoryObj } from '@storybook/react'; +import { ReactQueryDecorator } from '../../../../../storybook/decorators/react-query'; +import { ReduxDecorator } from '../../../../../storybook/decorators/redux-decorator'; +import { NativeQueryRelationshipWidget } from './NativeQueryRelationshipWidget'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; +import { expect } from '@storybook/jest'; +import { handlers } from '../mocks/handlers'; +import { useState } from 'react'; +import { NativeQueryRelationshipFormSchema } from '../schema'; + +export default { + component: NativeQueryRelationshipWidget, + decorators: [ + ReactQueryDecorator(), + ReduxDecorator({ + tables: { + dataHeaders: { + 'x-hasura-admin-secret': 'myadminsecretkey' as any, + }, + }, + }), + ], +} as Meta; + +export const DefaultView: StoryObj = { + render: () => { + return ( + + ); + }, +}; + +export const TestBasicInteraction: StoryObj< + typeof NativeQueryRelationshipWidget +> = { + render: () => { + const [formValues, setFormValues] = + useState(); + return ( +
+ setFormValues(data)} + /> +
{JSON.stringify(formValues)}
+
+ ); + }, + parameters: { + msw: handlers(), + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await waitFor( + async () => { + return await expect( + canvas.getByLabelText('Relationship Name') + ).toBeInTheDocument(); + }, + { + timeout: 5000, + } + ); + + // console.log(await canvas.getByLabelText('Relationship Name')); + await userEvent.type( + await canvas.getByLabelText('Relationship Name'), + 'articles' + ); + + await userEvent.selectOptions( + await canvas.getByLabelText('Target Native Query'), + 'get_article' + ); + + await userEvent.selectOptions( + await canvas.getByLabelText('Relationship Type'), + 'array' + ); + + await waitFor( + async () => { + return await expect( + canvas.getByTestId('columnMapping_source_input_0') + ).toBeInTheDocument(); + }, + { + timeout: 5000, + } + ); + + await userEvent.selectOptions( + await canvas.getByTestId('columnMapping_source_input_0'), + 'id' + ); + + await userEvent.selectOptions( + await canvas.getByTestId('columnMapping_target_input_0'), + 'author_id' + ); + + await userEvent.click(canvas.getByText('Add Relationship')); + + await waitFor(async () => { + return await expect(await canvas.getByTestId('result')).toHaveTextContent( + JSON.stringify({ + name: 'articles', + toNativeQuery: 'get_article', + type: 'array', + columnMapping: { id: 'author_id' }, + }) + ); + }); + }, +}; diff --git a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/TrackNativeQueryRelationshipForm.tsx b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/TrackNativeQueryRelationshipForm.tsx index c1c739614f0..bdf92a436dd 100644 --- a/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/TrackNativeQueryRelationshipForm.tsx +++ b/frontend/libs/console/legacy-ce/src/lib/features/Data/LogicalModels/NativeQueryRelationships/components/TrackNativeQueryRelationshipForm.tsx @@ -28,6 +28,7 @@ export const TrackNativeQueryRelationshipForm = ({ label="Relationship Name" placeholder="Name your native query relationship" name={'name'} + dataTestId="relationship_name" />