From a476c47816a46b4cc3dcf41db003e7f665501695 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 13 Dec 2023 14:13:54 +0100 Subject: [PATCH 01/15] Fix mock implementations --- frontend/app-development/App.test.tsx | 9 - .../overview/components/Overview.test.tsx | 10 - .../app-development/layout/AppShell.test.tsx | 24 +-- .../SettingsModal/SettingsModal.test.tsx | 10 - .../Tabs/SetupTab/SetupTab.test.tsx | 9 - .../src/views/LandingPage.test.tsx | 13 -- .../packages/shared/src/mocks/queriesMock.ts | 184 +++++++++--------- .../containers/DesignView/DesignView.test.tsx | 10 - .../packages/ux-editor/src/testing/mocks.tsx | 4 +- .../ResourceDashboardPage.test.tsx | 10 - .../pages/ResourcePage/ResourcePage.test.tsx | 10 - 11 files changed, 102 insertions(+), 191 deletions(-) diff --git a/frontend/app-development/App.test.tsx b/frontend/app-development/App.test.tsx index 980f0775245..5d95a1460c0 100644 --- a/frontend/app-development/App.test.tsx +++ b/frontend/app-development/App.test.tsx @@ -11,8 +11,6 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; jest.mock('../language/src/nb.json', jest.fn()); jest.mock('../language/src/en.json', jest.fn()); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; const render = async (remainingMinutes: number = 40) => { renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/my-org/my-app`, @@ -27,14 +25,7 @@ const render = async (remainingMinutes: number = 40) => { }); }; describe('App', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); diff --git a/frontend/app-development/features/overview/components/Overview.test.tsx b/frontend/app-development/features/overview/components/Overview.test.tsx index f6d5ade1826..cec264b2657 100644 --- a/frontend/app-development/features/overview/components/Overview.test.tsx +++ b/frontend/app-development/features/overview/components/Overview.test.tsx @@ -11,18 +11,8 @@ const org = 'org'; const app = 'app'; const title = 'test'; -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - describe('Overview', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); it('renders component', async () => { diff --git a/frontend/app-development/layout/AppShell.test.tsx b/frontend/app-development/layout/AppShell.test.tsx index c4248403305..ee8255728a7 100644 --- a/frontend/app-development/layout/AppShell.test.tsx +++ b/frontend/app-development/layout/AppShell.test.tsx @@ -13,9 +13,6 @@ import { RoutePaths } from 'app-development/enums/RoutePaths'; const mockOrg: string = 'org'; const mockApp: string = 'app'; -const getRepoStatus = jest.fn().mockImplementation(() => Promise.resolve({})); -const getUser = jest.fn().mockImplementation(() => Promise.resolve({})); - const mockRepoStatus: RepoStatus = { aheadBy: 0, behindBy: 0, @@ -40,18 +37,8 @@ jest.mock('react-router-dom', () => ({ }), })); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - describe('App', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); @@ -97,18 +84,17 @@ describe('App', () => { }); const resolveAndWaitForSpinnerToDisappear = async (queries: Partial = {}) => { - getRepoStatus.mockImplementation(() => Promise.resolve(mockRepoStatus)); - getUser.mockImplementation(() => Promise.resolve(mockUser)); - - render(queries); + render({ + ...queries, + getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve(mockRepoStatus)), + getUser: jest.fn().mockImplementation(() => Promise.resolve(mockUser)), + }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); }; const render = async (queries: Partial = {}) => { const allQueries: ServicesContextProps = { ...queriesMock, - getRepoStatus, - getUser, ...queries, }; diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx index 944cb5e8d69..dee6a18c872 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx @@ -24,9 +24,6 @@ jest.mock('react-router-dom', () => ({ }), })); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - jest.mock('../../../hooks/mutations/useAppConfigMutation'); const updateAppConfigMutation = jest.fn(); const mockUpdateAppConfigMutation = useAppConfigMutation as jest.MockedFunction< @@ -45,14 +42,7 @@ const defaultProps: SettingsModalProps = { }; describe('SettingsModal', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/SetupTab/SetupTab.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/SetupTab/SetupTab.test.tsx index b0897e2c578..91c41218c10 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/SetupTab/SetupTab.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/SetupTab/SetupTab.test.tsx @@ -14,22 +14,13 @@ const mockApp: string = 'testApp'; const getAppMetadata = jest.fn().mockImplementation(() => Promise.resolve({})); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; const defaultProps: SetupTabProps = { org: mockOrg, app: mockApp, }; describe('SetupTab Component', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); diff --git a/frontend/app-preview/src/views/LandingPage.test.tsx b/frontend/app-preview/src/views/LandingPage.test.tsx index c55f4dc86ac..c3f9961eb6a 100644 --- a/frontend/app-preview/src/views/LandingPage.test.tsx +++ b/frontend/app-preview/src/views/LandingPage.test.tsx @@ -5,20 +5,7 @@ import { LandingPage } from './LandingPage'; import { renderWithMockStore } from '../../../../frontend/packages/ux-editor/src/testing/mocks'; import { textMock } from '../../../testing/mocks/i18nMock'; -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - describe('LandingPage', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); - afterEach(() => { - global.console = realConsole; - }); - it('should render an iframe', () => { const { renderResult } = renderWithMockStore()(); diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts index 16619877477..6e377e56b79 100644 --- a/frontend/packages/shared/src/mocks/queriesMock.ts +++ b/frontend/packages/shared/src/mocks/queriesMock.ts @@ -2,93 +2,99 @@ import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import inputComponentSchema from '../../../ux-editor/src/testing/schemas/json/component/Input.schema.v1.json'; import commonDefsComponentSchema from '../../../ux-editor/src/testing/schemas/json/component/Input.schema.v1.json'; export const queriesMock: ServicesContextProps = { - addAppAttachmentMetadata: jest.fn(), - addLanguageCode: jest.fn(), - addLayoutSet: jest.fn(), - addRepo: jest.fn(), - addXsdFromRepo: jest.fn(), - commitAndPushChanges: jest.fn(), - configureLayoutSet: jest.fn(), - copyApp: jest.fn(), - createDatamodel: jest.fn(), - createDeployment: jest.fn(), - createRelease: jest.fn(), - createRepoCommit: jest.fn(), - createResource: jest.fn(), - deleteAppAttachmentMetadata: jest.fn(), - deleteDatamodel: jest.fn(), - deleteFormLayout: jest.fn(), - deleteLanguageCode: jest.fn(), - generateModels: jest.fn(), - getAppReleases: jest.fn(), - getBranchStatus: jest.fn(), - getComponentSchema: jest.fn().mockResolvedValue(inputComponentSchema), - getComponentsCommonDefsSchema: jest.fn().mockResolvedValue(commonDefsComponentSchema), - getDatamodel: jest.fn(), - getDatamodelMetadata: jest.fn(), - getDatamodelsJson: jest.fn(), - getDatamodelsXsd: jest.fn(), - getDeployPermissions: jest.fn(), - getDeployments: jest.fn(), - getEnvironments: jest.fn(), - getExpressionSchema: jest.fn(), - getFormLayoutSettings: jest.fn(), - getFormLayouts: jest.fn(), - getFrontEndSettings: jest.fn(), - getInstanceIdForPreview: jest.fn(), - getLayoutSchema: jest.fn(), - getLayoutSets: jest.fn(), - getNewsList: jest.fn(), - getNumberFormatSchema: jest.fn(), - getOptionListIds: jest.fn(), - getOrgList: jest.fn(), - getOrganizations: jest.fn(), - getPolicy: jest.fn(), - getPolicyActions: jest.fn(), - getPolicySubjects: jest.fn(), - getRepoMetadata: jest.fn(), - getRepoPull: jest.fn(), - getRepoStatus: jest.fn(), - getResource: jest.fn(), - getResourceList: jest.fn(), - getResourcePublishStatus: jest.fn(), - getRuleConfig: jest.fn(), - getRuleModel: jest.fn(), - getStarredRepos: jest.fn(), - getTextLanguages: jest.fn(), - getTextResources: jest.fn(), - getUser: jest.fn(), - getValidatePolicy: jest.fn(), - getValidateResource: jest.fn(), - getWidgetSettings: jest.fn(), - logout: jest.fn(), - pushRepoChanges: jest.fn(), - resetRepoChanges: jest.fn(), - saveDatamodel: jest.fn(), - saveFormLayout: jest.fn(), - saveFormLayoutSettings: jest.fn(), - saveRuleConfig: jest.fn(), - searchRepos: jest.fn(), - setStarredRepo: jest.fn(), - unsetStarredRepo: jest.fn(), - updateAppAttachmentMetadata: jest.fn(), - updateFormLayoutName: jest.fn(), - updatePolicy: jest.fn(), - updateResource: jest.fn(), - updateTextId: jest.fn(), - updateTranslationByLangCode: jest.fn(), - upsertTextResources: jest.fn(), - getBpmnFile: jest.fn(), - updateBpmnXml: jest.fn(), - getAppPolicy: jest.fn(), - updateAppPolicy: jest.fn(), - getAppConfig: jest.fn(), - getAppMetadata: jest.fn(), - updateAppMetadata: jest.fn(), - updateAppConfig: jest.fn(), - getRepoInitialCommit: jest.fn(), - publishResource: jest.fn(), - getAltinn2LinkServices: jest.fn(), - importResourceFromAltinn2: jest.fn(), - getAppLibVersion: jest.fn(), + addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + addLanguageCode: jest.fn().mockImplementation(() => Promise.resolve({})), + addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), + addRepo: jest.fn().mockImplementation(() => Promise.resolve({})), + addXsdFromRepo: jest.fn().mockImplementation(() => Promise.resolve({})), + commitAndPushChanges: jest.fn().mockImplementation(() => Promise.resolve({})), + configureLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), + copyApp: jest.fn().mockImplementation(() => Promise.resolve({})), + createDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + createDeployment: jest.fn().mockImplementation(() => Promise.resolve({})), + createRelease: jest.fn().mockImplementation(() => Promise.resolve({})), + createRepoCommit: jest.fn().mockImplementation(() => Promise.resolve({})), + createResource: jest.fn().mockImplementation(() => Promise.resolve({})), + deleteAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + deleteDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + deleteFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), + deleteLanguageCode: jest.fn().mockImplementation(() => Promise.resolve({})), + generateModels: jest.fn().mockImplementation(() => Promise.resolve({})), + getAppReleases: jest.fn().mockImplementation(() => Promise.resolve({})), + getBranchStatus: jest.fn().mockImplementation(() => Promise.resolve({})), + getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve(inputComponentSchema)), + getComponentsCommonDefsSchema: jest + .fn() + .mockImplementation(() => Promise.resolve(commonDefsComponentSchema)), + getDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelsJson: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve({})), + getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve({})), + getDeployments: jest.fn().mockImplementation(() => + Promise.resolve({ + results: [], + }), + ), + getEnvironments: jest.fn().mockImplementation(() => Promise.resolve({})), + getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve({})), + getFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve({})), + getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve({})), + getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve({})), + getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve({})), + getNewsList: jest.fn().mockImplementation(() => Promise.resolve({})), + getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve({})), + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve({})), + getOrgList: jest.fn().mockImplementation(() => Promise.resolve({})), + getOrganizations: jest.fn().mockImplementation(() => Promise.resolve({})), + getPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), + getPolicyActions: jest.fn().mockImplementation(() => Promise.resolve({})), + getPolicySubjects: jest.fn().mockImplementation(() => Promise.resolve({})), + getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(null)), + getRepoPull: jest.fn().mockImplementation(() => Promise.resolve({})), + getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve({})), + getResource: jest.fn().mockImplementation(() => Promise.resolve({})), + getResourceList: jest.fn().mockImplementation(() => Promise.resolve({})), + getResourcePublishStatus: jest.fn().mockImplementation(() => Promise.resolve({})), + getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve({})), + getRuleModel: jest.fn().mockImplementation(() => Promise.resolve({})), + getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve({})), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve({})), + getTextResources: jest.fn().mockImplementation(() => Promise.resolve([])), + getUser: jest.fn().mockImplementation(() => Promise.resolve({})), + getValidatePolicy: jest.fn().mockImplementation(() => Promise.resolve({})), + getValidateResource: jest.fn().mockImplementation(() => Promise.resolve({})), + getWidgetSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + logout: jest.fn().mockImplementation(() => Promise.resolve({})), + pushRepoChanges: jest.fn().mockImplementation(() => Promise.resolve({})), + resetRepoChanges: jest.fn().mockImplementation(() => Promise.resolve({})), + saveDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + saveFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), + saveFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + saveRuleConfig: jest.fn().mockImplementation(() => Promise.resolve({})), + searchRepos: jest.fn().mockImplementation(() => Promise.resolve({})), + setStarredRepo: jest.fn().mockImplementation(() => Promise.resolve({})), + unsetStarredRepo: jest.fn().mockImplementation(() => Promise.resolve({})), + updateAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + updateFormLayoutName: jest.fn().mockImplementation(() => Promise.resolve({})), + updatePolicy: jest.fn().mockImplementation(() => Promise.resolve({})), + updateResource: jest.fn().mockImplementation(() => Promise.resolve({})), + updateTextId: jest.fn().mockImplementation(() => Promise.resolve({})), + updateTranslationByLangCode: jest.fn().mockImplementation(() => Promise.resolve({})), + upsertTextResources: jest.fn().mockImplementation(() => Promise.resolve({})), + getBpmnFile: jest.fn().mockImplementation(() => Promise.resolve({})), + updateBpmnXml: jest.fn().mockImplementation(() => Promise.resolve({})), + getAppPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), + updateAppPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), + getAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), + getAppMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + updateAppMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + updateAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), + getRepoInitialCommit: jest.fn().mockImplementation(() => Promise.resolve({})), + publishResource: jest.fn().mockImplementation(() => Promise.resolve({})), + getAltinn2LinkServices: jest.fn().mockImplementation(() => Promise.resolve({})), + importResourceFromAltinn2: jest.fn().mockImplementation(() => Promise.resolve({})), + getAppLibVersion: jest.fn().mockImplementation(() => Promise.resolve({})), }; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx index d943f56620d..d77e2ee2604 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx @@ -33,18 +33,8 @@ jest.mock('react-router-dom', () => ({ }, })); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - describe('DesignView', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); diff --git a/frontend/packages/ux-editor/src/testing/mocks.tsx b/frontend/packages/ux-editor/src/testing/mocks.tsx index 7f450e983e5..b3f74e147e7 100644 --- a/frontend/packages/ux-editor/src/testing/mocks.tsx +++ b/frontend/packages/ux-editor/src/testing/mocks.tsx @@ -39,7 +39,7 @@ export const optionListIdsMock: string[] = ['test-1', 'test-2']; export const queriesMock: ServicesContextProps = { ...allQueriesMock, addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - addLayoutSet: jest.fn(), + addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), configureLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), deleteAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), deleteFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), @@ -50,7 +50,7 @@ export const queriesMock: ServicesContextProps = { .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)), getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - getInstanceIdForPreview: jest.fn(), + getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve({})), getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve(layoutSchema)), getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve(layoutSetsMock)), getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve(numberFormatSchema)), diff --git a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx index 4ceec5cbec7..240d5514078 100644 --- a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx +++ b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx @@ -64,18 +64,8 @@ jest.mock('react-router-dom', () => ({ }), })); -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - describe('ResourceDashBoardPage', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); it('fetches resource list on mount', () => { diff --git a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx index 481151ecc51..8f34ce4ff15 100644 --- a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx +++ b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx @@ -11,9 +11,6 @@ import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; -// Mocking console.error due to Tanstack Query removing custom logger between V4 and v5 see issue: #11692 -const realConsole = console; - const mockResource1: Resource = { identifier: 'r1', title: { nb: 'ressurs 1', nn: 'res1', en: 'resource 1' }, @@ -48,14 +45,7 @@ jest.mock('react-router-dom', () => ({ })); describe('ResourcePage', () => { - beforeEach(() => { - global.console = { - ...console, - error: jest.fn(), - }; - }); afterEach(() => { - global.console = realConsole; jest.clearAllMocks(); }); From fe3b75d1e5a4b686f2003086b030957b3c5c413f Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Sun, 17 Dec 2023 21:11:15 +0100 Subject: [PATCH 02/15] Cleanup mocks --- .../components/AppEnvironments.test.tsx | 6 +-- .../overview/components/AppLogs.test.tsx | 6 +-- .../overview/components/AppStatus.test.tsx | 6 +-- .../components/Documentation.test.tsx | 4 -- .../overview/components/Overview.test.tsx | 6 +-- .../features/textEditor/TextEditor.test.tsx | 2 +- .../hooks/queries/useAppDeploymentsQuery.ts | 2 +- frontend/app-development/layout/App.test.tsx | 2 - .../layout/PageLayout.test.tsx | 8 +--- .../SettingsModal/SettingsModal.test.tsx | 7 +-- .../AccessControlTab.test.tsx | 2 - .../LocalChangesTab/LocalChangesTab.test.tsx | 8 +--- frontend/app-development/test/testUtils.tsx | 2 + .../VersionControlButtons.test.tsx | 26 +++++------ .../packages/shared/src/mocks/queriesMock.ts | 46 ++++++++----------- .../packages/ux-editor/src/testing/mocks.tsx | 20 +++----- .../ImportResourceModal.test.tsx | 4 +- .../ServiceContent/ServiceContent.test.tsx | 2 - .../DeployResourcePage.test.tsx | 2 - .../PolicyEditorPage.test.tsx | 2 - .../ResourceDashboardPage.test.tsx | 2 - .../pages/ResourcePage/ResourcePage.test.tsx | 2 - 22 files changed, 49 insertions(+), 118 deletions(-) diff --git a/frontend/app-development/features/overview/components/AppEnvironments.test.tsx b/frontend/app-development/features/overview/components/AppEnvironments.test.tsx index f0392563b71..f4cc86ece57 100644 --- a/frontend/app-development/features/overview/components/AppEnvironments.test.tsx +++ b/frontend/app-development/features/overview/components/AppEnvironments.test.tsx @@ -3,7 +3,6 @@ import { screen, waitForElementToBeRemoved } from '@testing-library/react'; import { AppEnvironments } from './AppEnvironments'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; -import { queriesMock } from 'app-development/test/mocks'; import { textMock } from '../../../../testing/mocks/i18nMock'; // Test data @@ -13,10 +12,7 @@ const app = 'app'; const render = (queries = {}) => { return renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, - queries: { - ...queriesMock, - ...queries, - }, + queries, }); }; diff --git a/frontend/app-development/features/overview/components/AppLogs.test.tsx b/frontend/app-development/features/overview/components/AppLogs.test.tsx index 407d0c5b01d..08fe25a4f88 100644 --- a/frontend/app-development/features/overview/components/AppLogs.test.tsx +++ b/frontend/app-development/features/overview/components/AppLogs.test.tsx @@ -3,7 +3,6 @@ import { screen, waitForElementToBeRemoved } from '@testing-library/react'; import { AppLogs } from './AppLogs'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; -import { queriesMock } from 'app-development/test/mocks'; import { textMock } from '../../../../testing/mocks/i18nMock'; // Test data @@ -13,10 +12,7 @@ const app = 'test-ttd'; const render = (queries = {}) => { return renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, - queries: { - ...queriesMock, - ...queries, - }, + queries, }); }; diff --git a/frontend/app-development/features/overview/components/AppStatus.test.tsx b/frontend/app-development/features/overview/components/AppStatus.test.tsx index f2f72f10448..c6a349eaf3f 100644 --- a/frontend/app-development/features/overview/components/AppStatus.test.tsx +++ b/frontend/app-development/features/overview/components/AppStatus.test.tsx @@ -3,7 +3,6 @@ import { screen, waitForElementToBeRemoved } from '@testing-library/react'; import { AppStatus } from './AppStatus'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; -import { queriesMock } from 'app-development/test/mocks'; import { textMock } from '../../../../testing/mocks/i18nMock'; // Test data @@ -15,10 +14,7 @@ const envTypeTest = 'test'; const render = (queries = {}, envName = envNameTest, envType = envTypeTest) => { return renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, - queries: { - ...queriesMock, - ...queries, - }, + queries, }); }; diff --git a/frontend/app-development/features/overview/components/Documentation.test.tsx b/frontend/app-development/features/overview/components/Documentation.test.tsx index f62cd7b4b91..d980b5d60b5 100644 --- a/frontend/app-development/features/overview/components/Documentation.test.tsx +++ b/frontend/app-development/features/overview/components/Documentation.test.tsx @@ -4,7 +4,6 @@ import { Documentation } from './Documentation'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; import { textMock } from '../../../../testing/mocks/i18nMock'; -import { queriesMock } from 'app-development/test/mocks'; // Test data const org = 'my-org'; @@ -14,9 +13,6 @@ describe('Documentation', () => { it('renders component', async () => { renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, - queries: { - ...queriesMock, - }, }); expect( diff --git a/frontend/app-development/features/overview/components/Overview.test.tsx b/frontend/app-development/features/overview/components/Overview.test.tsx index cec264b2657..69ee5ad0e05 100644 --- a/frontend/app-development/features/overview/components/Overview.test.tsx +++ b/frontend/app-development/features/overview/components/Overview.test.tsx @@ -3,7 +3,6 @@ import { screen } from '@testing-library/react'; import { Overview } from './Overview'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; -import { queriesMock } from 'app-development/test/mocks'; import { textMock } from '../../../../testing/mocks/i18nMock'; // Test data @@ -121,9 +120,6 @@ describe('Overview', () => { const render = (queries = {}) => { return renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, - queries: { - ...queriesMock, - ...queries, - }, + queries, }); }; diff --git a/frontend/app-development/features/textEditor/TextEditor.test.tsx b/frontend/app-development/features/textEditor/TextEditor.test.tsx index f7484a071f0..536ab071ede 100644 --- a/frontend/app-development/features/textEditor/TextEditor.test.tsx +++ b/frontend/app-development/features/textEditor/TextEditor.test.tsx @@ -24,7 +24,7 @@ const queriesMock: Partial = { value: testTextResourceValue, }, ], - }) + }), ), getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(languages)), }; diff --git a/frontend/app-development/hooks/queries/useAppDeploymentsQuery.ts b/frontend/app-development/hooks/queries/useAppDeploymentsQuery.ts index 0d568db1554..535aa3568e3 100644 --- a/frontend/app-development/hooks/queries/useAppDeploymentsQuery.ts +++ b/frontend/app-development/hooks/queries/useAppDeploymentsQuery.ts @@ -13,7 +13,7 @@ export const useAppDeploymentsQuery = ( const { getDeployments } = useServicesContext(); return useQuery({ queryKey: [QueryKey.AppDeployments, owner, app], - queryFn: () => getDeployments(owner, app).then((res) => res.results), + queryFn: () => getDeployments(owner, app).then((res) => res?.results || []), refetchInterval: DEPLOYMENTS_REFETCH_INTERVAL, meta, }); diff --git a/frontend/app-development/layout/App.test.tsx b/frontend/app-development/layout/App.test.tsx index d35bbb6a194..292b9f133b3 100644 --- a/frontend/app-development/layout/App.test.tsx +++ b/frontend/app-development/layout/App.test.tsx @@ -6,7 +6,6 @@ import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../test/testUtils'; import * as testids from '../../testing/testids'; import { textMock } from '../../testing/mocks/i18nMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; jest.mock('../../language/src/nb.json', jest.fn()); jest.mock('../../language/src/en.json', jest.fn()); @@ -14,7 +13,6 @@ jest.mock('../../language/src/en.json', jest.fn()); const render = async (remainingMinutes: number = 40) => { renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/my-org/my-app`, - queries: { ...queriesMock }, preloadedState: { userState: { session: { diff --git a/frontend/app-development/layout/PageLayout.test.tsx b/frontend/app-development/layout/PageLayout.test.tsx index d7d53025308..0a73d4c7361 100644 --- a/frontend/app-development/layout/PageLayout.test.tsx +++ b/frontend/app-development/layout/PageLayout.test.tsx @@ -4,7 +4,6 @@ import { screen, waitForElementToBeRemoved } from '@testing-library/react'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../test/testUtils'; import { textMock } from '../../testing/mocks/i18nMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { RepoStatus } from 'app-shared/types/RepoStatus'; import { User } from 'app-shared/types/User'; @@ -93,13 +92,8 @@ const resolveAndWaitForSpinnerToDisappear = async (queries: Partial = {}) => { - const allQueries: ServicesContextProps = { - ...queriesMock, - ...queries, - }; - renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/my-org/my-app/${RoutePaths.Overview}`, - queries: allQueries, + queries, }); }; diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx index 21bbf3bd31b..57753d51fc4 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/SettingsModal.test.tsx @@ -11,7 +11,6 @@ import { textMock } from '../../../../testing/mocks/i18nMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { QueryClient, UseMutationResult } from '@tanstack/react-query'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { AppConfig } from 'app-shared/types/AppConfig'; import { useAppConfigMutation } from 'app-development/hooks/mutations'; import { MemoryRouter } from 'react-router-dom'; @@ -245,13 +244,9 @@ const render = ( queries: Partial = {}, queryClient: QueryClient = createQueryClientMock(), ) => { - const allQueries: ServicesContextProps = { - ...queriesMock, - ...queries, - }; return rtlRender( - + , diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/AccessControlTab/AccessControlTab.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/AccessControlTab/AccessControlTab.test.tsx index 0689e9ff5e1..fad6454ae40 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/AccessControlTab/AccessControlTab.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/AccessControlTab/AccessControlTab.test.tsx @@ -8,7 +8,6 @@ import { import { AccessControlTab, AccessControlTabProps } from './AccessControlTab'; import { textMock } from '../../../../../../../testing/mocks/i18nMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient, UseMutationResult } from '@tanstack/react-query'; import userEvent from '@testing-library/user-event'; @@ -138,7 +137,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getAppMetadata, ...queries, }; diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/LocalChangesTab/LocalChangesTab.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/LocalChangesTab/LocalChangesTab.test.tsx index 842ee1355dd..62088bb795c 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/LocalChangesTab/LocalChangesTab.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/components/Tabs/LocalChangesTab/LocalChangesTab.test.tsx @@ -3,7 +3,6 @@ import { act, render as rtlRender, screen } from '@testing-library/react'; import { LocalChangesTab, LocalChangesTabProps } from './LocalChangesTab'; import { textMock } from '../../../../../../../testing/mocks/i18nMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient, UseMutationResult } from '@tanstack/react-query'; import userEvent from '@testing-library/user-event'; @@ -137,13 +136,8 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), props: LocalChangesTabProps, ) => { - const allQueries: ServicesContextProps = { - ...queriesMock, - ...queries, - }; - return rtlRender( - + , ); diff --git a/frontend/app-development/test/testUtils.tsx b/frontend/app-development/test/testUtils.tsx index 97cf1a6383a..caf4efcd5b8 100644 --- a/frontend/app-development/test/testUtils.tsx +++ b/frontend/app-development/test/testUtils.tsx @@ -10,6 +10,7 @@ import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { queryClientConfigMock } from 'app-shared/mocks/queryClientMock'; import { QueryClient } from '@tanstack/react-query'; +import { queriesMock } from './mocks'; interface ExtendedRenderOptions extends Omit { preloadedState?: PreloadedState; @@ -35,6 +36,7 @@ export const renderWithProviders = ( Promise.resolve(okRepoS const getRepoPull = jest.fn().mockImplementation(() => Promise.resolve(okRepoStatus)); const commitAndPushChanges = jest.fn().mockImplementation(() => Promise.resolve(okRepoStatus)); -const defaultQueries: ServicesContextProps = { - ...queriesMock, +const defaultQueries: Partial = { getRepoMetadata, getRepoStatus, getRepoPull, @@ -103,7 +101,7 @@ describe('Shared > Version Control > VersionControlHeader', () => { await act(() => user.click(shareButton)); await waitFor(() => expect(mockGetRepoStatus).toHaveBeenCalledTimes(1)); expect( - await screen.findByText(textMock('sync_header.describe_and_validate')) + await screen.findByText(textMock('sync_header.describe_and_validate')), ).toBeInTheDocument(); }); @@ -134,7 +132,7 @@ describe('Shared > Version Control > VersionControlHeader', () => { await act(() => user.click(shareButton)); await waitFor(() => expect(mockGetRepoStatus).toHaveBeenCalledTimes(1)); expect( - await screen.findByText(textMock('sync_header.describe_and_validate')) + await screen.findByText(textMock('sync_header.describe_and_validate')), ).toBeInTheDocument(); }); @@ -153,8 +151,8 @@ describe('Shared > Version Control > VersionControlHeader', () => { await waitFor(() => expect(mockGetRepoStatus).toHaveBeenCalledTimes(1)); await act(() => user.click( - screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }) - ) + screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }), + ), ); await waitFor(() => expect(commitAndPushChanges).toHaveBeenCalledTimes(1)); }); @@ -177,8 +175,8 @@ describe('Shared > Version Control > VersionControlHeader', () => { await waitFor(() => expect(mockGetRepoStatus).toHaveBeenCalledTimes(1)); await act(() => user.click( - screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }) - ) + screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }), + ), ); await waitFor(() => expect(mockCommitAndPushChanges).toHaveBeenCalledTimes(1)); await waitFor(() => expect(mockConsoleError).toHaveBeenCalledTimes(1)); @@ -207,22 +205,22 @@ describe('Shared > Version Control > VersionControlHeader', () => { await waitFor(() => expect(mockGetRepoStatus).toHaveBeenCalledTimes(1)); await act(() => user.click( - screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }) - ) + screen.getByRole('button', { name: textMock('sync_header.describe_and_validate_btnText') }), + ), ); expect(mockConsoleError).toHaveBeenCalled(); expect( - await screen.findByText(textMock('sync_header.merge_conflict_occured')) + await screen.findByText(textMock('sync_header.merge_conflict_occured')), ).toBeInTheDocument(); }); }); const render = ( props: Partial = {}, - queries: Partial = {} + queries: Partial = {}, ) => renderRtl( - + , ); diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts index 6e377e56b79..5a918585022 100644 --- a/frontend/packages/shared/src/mocks/queriesMock.ts +++ b/frontend/packages/shared/src/mocks/queriesMock.ts @@ -1,6 +1,4 @@ import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; -import inputComponentSchema from '../../../ux-editor/src/testing/schemas/json/component/Input.schema.v1.json'; -import commonDefsComponentSchema from '../../../ux-editor/src/testing/schemas/json/component/Input.schema.v1.json'; export const queriesMock: ServicesContextProps = { addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), addLanguageCode: jest.fn().mockImplementation(() => Promise.resolve({})), @@ -22,47 +20,41 @@ export const queriesMock: ServicesContextProps = { generateModels: jest.fn().mockImplementation(() => Promise.resolve({})), getAppReleases: jest.fn().mockImplementation(() => Promise.resolve({})), getBranchStatus: jest.fn().mockImplementation(() => Promise.resolve({})), - getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve(inputComponentSchema)), - getComponentsCommonDefsSchema: jest - .fn() - .mockImplementation(() => Promise.resolve(commonDefsComponentSchema)), + getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getComponentsCommonDefsSchema: jest.fn().mockImplementation(() => Promise.resolve([])), getDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - getDatamodelsJson: jest.fn().mockImplementation(() => Promise.resolve({})), - getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve({})), - getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve({})), - getDeployments: jest.fn().mockImplementation(() => - Promise.resolve({ - results: [], - }), - ), - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve({})), - getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelsJson: jest.fn().mockImplementation(() => Promise.resolve([])), + getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve([])), + getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve([])), + getDeployments: jest.fn().mockImplementation(() => Promise.resolve({})), + getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), + getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve([])), getFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve({})), getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve({})), - getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve({})), + getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve([])), getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve({})), getNewsList: jest.fn().mockImplementation(() => Promise.resolve({})), - getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve({})), - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve({})), + getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve([])), getOrgList: jest.fn().mockImplementation(() => Promise.resolve({})), - getOrganizations: jest.fn().mockImplementation(() => Promise.resolve({})), + getOrganizations: jest.fn().mockImplementation(() => Promise.resolve([])), getPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - getPolicyActions: jest.fn().mockImplementation(() => Promise.resolve({})), - getPolicySubjects: jest.fn().mockImplementation(() => Promise.resolve({})), + getPolicyActions: jest.fn().mockImplementation(() => Promise.resolve([])), + getPolicySubjects: jest.fn().mockImplementation(() => Promise.resolve([])), getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(null)), getRepoPull: jest.fn().mockImplementation(() => Promise.resolve({})), getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve({})), getResource: jest.fn().mockImplementation(() => Promise.resolve({})), - getResourceList: jest.fn().mockImplementation(() => Promise.resolve({})), + getResourceList: jest.fn().mockImplementation(() => Promise.resolve([])), getResourcePublishStatus: jest.fn().mockImplementation(() => Promise.resolve({})), getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve({})), getRuleModel: jest.fn().mockImplementation(() => Promise.resolve({})), - getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve({})), - getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve({})), - getTextResources: jest.fn().mockImplementation(() => Promise.resolve([])), + getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve([])), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve([])), + getTextResources: jest.fn().mockImplementation(() => Promise.resolve({})), getUser: jest.fn().mockImplementation(() => Promise.resolve({})), getValidatePolicy: jest.fn().mockImplementation(() => Promise.resolve({})), getValidateResource: jest.fn().mockImplementation(() => Promise.resolve({})), @@ -94,7 +86,7 @@ export const queriesMock: ServicesContextProps = { updateAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), getRepoInitialCommit: jest.fn().mockImplementation(() => Promise.resolve({})), publishResource: jest.fn().mockImplementation(() => Promise.resolve({})), - getAltinn2LinkServices: jest.fn().mockImplementation(() => Promise.resolve({})), + getAltinn2LinkServices: jest.fn().mockImplementation(() => Promise.resolve([])), importResourceFromAltinn2: jest.fn().mockImplementation(() => Promise.resolve({})), getAppLibVersion: jest.fn().mockImplementation(() => Promise.resolve({})), }; diff --git a/frontend/packages/ux-editor/src/testing/mocks.tsx b/frontend/packages/ux-editor/src/testing/mocks.tsx index b3f74e147e7..b7afb0e9723 100644 --- a/frontend/packages/ux-editor/src/testing/mocks.tsx +++ b/frontend/packages/ux-editor/src/testing/mocks.tsx @@ -24,6 +24,8 @@ import numberFormatSchema from './schemas/json/layout/number-format.schema.v1.js import layoutSchema from './schemas/json/layout/layout.schema.v1.json'; import { AppContext, AppContextProps } from '../AppContext'; import { appContextMock } from './appContextMock'; +import inputComponentSchema from './schemas/json/component/Input.schema.v1.json'; +import commonDefsComponentSchema from './schemas/json/component/Input.schema.v1.json'; export const formLayoutSettingsMock: ILayoutSettings = { pages: { @@ -38,19 +40,12 @@ export const optionListIdsMock: string[] = ['test-1', 'test-2']; export const queriesMock: ServicesContextProps = { ...allQueriesMock, - addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), - configureLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({ elements: {} })), getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve(expressionSchema)), getFormLayoutSettings: jest .fn() .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)), - getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve({})), getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve(layoutSchema)), getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve(layoutSetsMock)), getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve(numberFormatSchema)), @@ -58,13 +53,10 @@ export const queriesMock: ServicesContextProps = { getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfigMock)), getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), - getTextResources: jest.fn().mockImplementation(() => Promise.resolve([])), - getWidgetSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - saveFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), - saveFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - updateAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - updateFormLayoutName: jest.fn().mockImplementation(() => Promise.resolve({})), - upsertTextResources: jest.fn().mockImplementation(() => Promise.resolve()), + getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve(inputComponentSchema)), + getComponentsCommonDefsSchema: jest + .fn() + .mockImplementation(() => Promise.resolve(commonDefsComponentSchema)), }; export const queryClientMock = new QueryClient({ diff --git a/frontend/resourceadm/components/ImportResourceModal/ImportResourceModal.test.tsx b/frontend/resourceadm/components/ImportResourceModal/ImportResourceModal.test.tsx index 2e44b02dbb1..cdfe11641f9 100644 --- a/frontend/resourceadm/components/ImportResourceModal/ImportResourceModal.test.tsx +++ b/frontend/resourceadm/components/ImportResourceModal/ImportResourceModal.test.tsx @@ -6,7 +6,6 @@ import { textMock } from '../../../testing/mocks/i18nMock'; import { act } from 'react-dom/test-utils'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { Altinn2LinkService } from 'app-shared/types/Altinn2LinkService'; @@ -108,8 +107,7 @@ describe('ImportResourceModal', () => { }); const render = (props: Partial = {}) => { - const allQueries: ServicesContextProps = { - ...queriesMock, + const allQueries: Partial = { getAltinn2LinkServices, importResourceFromAltinn2, }; diff --git a/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx b/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx index 84ba0735bf1..336e0e92b8b 100644 --- a/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx +++ b/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx @@ -12,7 +12,6 @@ import userEvent from '@testing-library/user-event'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; const mockSelectedContext: string = 'selectedContext'; const mockEnv: string = 'env1'; @@ -130,7 +129,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getAltinn2LinkServices, ...queries, }; diff --git a/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx b/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx index 77879000143..b235bf82ab0 100644 --- a/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx +++ b/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx @@ -8,7 +8,6 @@ import { import { DeployResourcePage, DeployResourcePageProps } from './DeployResourcePage'; import { textMock } from '../../../testing/mocks/i18nMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient, UseMutationResult } from '@tanstack/react-query'; @@ -410,7 +409,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getRepoStatus, getResourcePublishStatus, getValidatePolicy, diff --git a/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx b/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx index f6570c63b8c..89aee9e80f7 100644 --- a/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx +++ b/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx @@ -3,7 +3,6 @@ import { render as rtlRender, screen, waitForElementToBeRemoved } from '@testing import { PolicyEditorPage, PolicyEditorPageProps } from './PolicyEditorPage'; import { textMock } from '../../../testing/mocks/i18nMock'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; @@ -119,7 +118,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getPolicy, getPolicyActions, getPolicySubjects, diff --git a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx index 240d5514078..8f3783bdb64 100644 --- a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx +++ b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx @@ -6,7 +6,6 @@ import { act } from 'react-dom/test-utils'; import { textMock } from '../../../testing/mocks/i18nMock'; import { ResourceListItem } from 'app-shared/types/ResourceAdm'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; @@ -238,7 +237,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getResourceList, getOrganizations, ...queries, diff --git a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx index 8f34ce4ff15..fdd10d2891f 100644 --- a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx +++ b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx @@ -6,7 +6,6 @@ import { act } from 'react-dom/test-utils'; import { textMock } from '../../../testing/mocks/i18nMock'; import { Resource } from 'app-shared/types/ResourceAdm'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; @@ -150,7 +149,6 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - ...queriesMock, getValidatePolicy, getValidateResource, getResource, From 4f3c8c974cd652d3a2581f6ab37bfa9c4e47cb12 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Mon, 18 Dec 2023 13:47:46 +0100 Subject: [PATCH 03/15] Remove extra queriesMock --- .../useResetRepositoryMutation.test.ts | 3 +- frontend/app-development/test/mocks.tsx | 58 ++++++++++------ frontend/app-development/test/testUtils.tsx | 2 +- .../useRepoCommitAndPushMutation.test.ts | 3 +- .../useUpsertTextResourcesMutation.test.ts | 18 +++-- .../queries/useTextResourcesQuery.test.ts | 10 ++- .../src/components/TextResource.test.tsx | 62 +++++++++++------ .../src/components/TextResourceEdit.test.tsx | 8 +-- .../containers/DesignView/DesignView.test.tsx | 2 +- .../NavigationMenu/NavigationMenu.test.tsx | 7 +- ...seAddAppAttachmentMetadataMutation.test.ts | 17 ++--- .../useAddFormContainerMutation.test.ts | 3 +- .../useAddItemToLayoutMutation.test.ts | 28 ++++---- .../mutations/useAddLayoutMutation.test.ts | 3 +- .../mutations/useAddWidgetMutation.test.ts | 22 +++++-- .../useConfigureLayoutSetMutation.test.ts | 25 +++---- ...eleteAppAttachmentMetadataMutation.test.ts | 9 +-- .../useDeleteFormComponentMutation.test.ts | 21 +++--- .../useDeleteFormContainerMutation.test.ts | 22 ++++--- .../mutations/useDeleteLayoutMutation.test.ts | 45 ++++++++++--- .../mutations/useFormLayoutMutation.test.tsx | 3 +- .../useFormLayoutSettingsMutation.test.ts | 11 ++-- .../mutations/useRuleConfigMutation.test.ts | 22 +++++-- ...pdateAppAttachmentMetadataMutation.test.ts | 17 ++--- .../useUpdateFormComponentMutation.test.ts | 66 +++++++++---------- ...seUpdateFormComponentOrderMutation.test.ts | 25 +++---- .../useUpdateFormContainerMutation.test.ts | 32 +++++---- .../useUpdateLayoutNameMutation.test.ts | 32 ++++++--- .../useUpdateLayoutOrderMutation.test.ts | 40 ++++++----- .../queries/useFrontEndSettingsQuery.test.ts | 3 +- .../hooks/queries/useRuleModelQuery.test.ts | 23 ++++--- .../packages/ux-editor/src/testing/mocks.tsx | 37 +---------- 32 files changed, 393 insertions(+), 286 deletions(-) diff --git a/frontend/app-development/hooks/mutations/useResetRepositoryMutation.test.ts b/frontend/app-development/hooks/mutations/useResetRepositoryMutation.test.ts index 0de0601b572..5cfa8dac575 100644 --- a/frontend/app-development/hooks/mutations/useResetRepositoryMutation.test.ts +++ b/frontend/app-development/hooks/mutations/useResetRepositoryMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../test/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../test/mocks'; import { useResetRepositoryMutation } from './useResetRepositoryMutation'; // Test data: diff --git a/frontend/app-development/test/mocks.tsx b/frontend/app-development/test/mocks.tsx index 3939bcdfb40..b4d3e839495 100644 --- a/frontend/app-development/test/mocks.tsx +++ b/frontend/app-development/test/mocks.tsx @@ -8,49 +8,69 @@ import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contex import { BrowserRouter } from 'react-router-dom'; import { PreviewConnectionContextProvider } from 'app-shared/providers/PreviewConnectionContext'; -import { queriesMock as allQueriesMock } from 'app-shared/mocks/queriesMock'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; import { rootStateMock } from './rootStateMock'; import { QueryClient } from '@tanstack/react-query'; import { queryClientConfigMock } from 'app-shared/mocks/queryClientMock'; export const textLanguagesMock = ['nb', 'nn', 'en']; -export const queriesMock: ServicesContextProps = { - ...allQueriesMock, -}; - export const renderWithMockStore = - (state: Partial = {}, queries: Partial = {}, queryClient?: QueryClient) => + ( + state: Partial = {}, + queries: Partial = {}, + queryClient?: QueryClient, + ) => (component: ReactNode) => { const store = configureStore()({ ...rootStateMock, ...state }); const renderResult = render( - + {component} - - ); - const rerender = (rerenderedComponent) => renderResult.rerender( - - - - {rerenderedComponent} - - - + , ); + const rerender = (rerenderedComponent) => + renderResult.rerender( + + + + {rerenderedComponent} + + + , + ); return { renderResult: { ...renderResult, rerender }, store }; }; export const renderHookWithMockStore = - (state: Partial = {}, queries: Partial = {}, queryClient?: QueryClient) => + ( + state: Partial = {}, + queries: Partial = {}, + queryClient?: QueryClient, + ) => (hook: () => any) => { const store = configureStore()({ ...rootStateMock, ...state }); const renderHookResult = renderHook(hook, { wrapper: ({ children }) => ( - + {children} diff --git a/frontend/app-development/test/testUtils.tsx b/frontend/app-development/test/testUtils.tsx index caf4efcd5b8..9562f6e7c73 100644 --- a/frontend/app-development/test/testUtils.tsx +++ b/frontend/app-development/test/testUtils.tsx @@ -10,7 +10,7 @@ import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { queryClientConfigMock } from 'app-shared/mocks/queryClientMock'; import { QueryClient } from '@tanstack/react-query'; -import { queriesMock } from './mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; interface ExtendedRenderOptions extends Omit { preloadedState?: PreloadedState; diff --git a/frontend/packages/shared/src/hooks/mutations/useRepoCommitAndPushMutation.test.ts b/frontend/packages/shared/src/hooks/mutations/useRepoCommitAndPushMutation.test.ts index 1e22dd3bdc5..569274c0311 100644 --- a/frontend/packages/shared/src/hooks/mutations/useRepoCommitAndPushMutation.test.ts +++ b/frontend/packages/shared/src/hooks/mutations/useRepoCommitAndPushMutation.test.ts @@ -1,5 +1,6 @@ import { CreateRepoCommitPayload } from 'app-shared/types/api'; -import { queriesMock, renderHookWithMockStore } from 'app-development/test/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from 'app-development/test/mocks'; import { useRepoCommitAndPushMutation } from './useRepoCommitAndPushMutation'; // Test data: diff --git a/frontend/packages/shared/src/hooks/mutations/useUpsertTextResourcesMutation.test.ts b/frontend/packages/shared/src/hooks/mutations/useUpsertTextResourcesMutation.test.ts index 0482a5c9089..2a4afedac88 100644 --- a/frontend/packages/shared/src/hooks/mutations/useUpsertTextResourcesMutation.test.ts +++ b/frontend/packages/shared/src/hooks/mutations/useUpsertTextResourcesMutation.test.ts @@ -1,7 +1,11 @@ -import { queriesMock, renderHookWithMockStore } from '../../../../ux-editor/src/testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../../../ux-editor/src/testing/mocks'; import { waitFor } from '@testing-library/react'; import { useTextResourcesQuery } from '../../../../../app-development/hooks/queries'; -import { UpsertTextResourcesMutationArgs, useUpsertTextResourcesMutation } from './useUpsertTextResourcesMutation'; +import { + UpsertTextResourcesMutationArgs, + useUpsertTextResourcesMutation, +} from './useUpsertTextResourcesMutation'; import { ITextResource } from 'app-shared/types/global'; // Test data: @@ -18,12 +22,16 @@ describe('useUpsertTextResourcesMutation', () => { const { result: upsertTextResources } = await renderUpsertTextResourcesMutation(); await upsertTextResources.current.mutateAsync(args); expect(queriesMock.upsertTextResources).toHaveBeenCalledTimes(1); - expect(queriesMock.upsertTextResources).toHaveBeenCalledWith(org, app, language, { [textId]: textValue }); + expect(queriesMock.upsertTextResources).toHaveBeenCalledWith(org, app, language, { + [textId]: textValue, + }); }); }); const renderUpsertTextResourcesMutation = async () => { - const { result: texts } = renderHookWithMockStore()(() => useTextResourcesQuery(org, app)).renderHookResult; + const { result: texts } = renderHookWithMockStore()(() => + useTextResourcesQuery(org, app), + ).renderHookResult; await waitFor(() => expect(texts.current.isSuccess).toBe(true)); return renderHookWithMockStore()(() => useUpsertTextResourcesMutation(org, app)).renderHookResult; -} +}; diff --git a/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts b/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts index 630c10de156..825b45b8d59 100644 --- a/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts +++ b/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts @@ -1,4 +1,8 @@ -import { queriesMock, renderHookWithMockStore, textLanguagesMock } from '../../../../ux-editor/src/testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { + renderHookWithMockStore, + textLanguagesMock, +} from '../../../../ux-editor/src/testing/mocks'; import { useTextResourcesQuery } from './useTextResourcesQuery'; import { waitFor } from '@testing-library/react'; @@ -8,7 +12,9 @@ const app = 'app'; describe('useTextResourcesQuery', () => { it('Calls getTextResources for each language', async () => { - const { result: resourcesResult } = renderHookWithMockStore()(() => useTextResourcesQuery(org, app)).renderHookResult; + const { result: resourcesResult } = renderHookWithMockStore()(() => + useTextResourcesQuery(org, app), + ).renderHookResult; await waitFor(() => expect(resourcesResult.current.isSuccess).toBe(true)); expect(queriesMock.getTextLanguages).toHaveBeenCalledTimes(1); expect(queriesMock.getTextLanguages).toHaveBeenCalledWith(org, app); diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index 97a2173a6ad..1c98bf21e1a 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -2,11 +2,7 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import type { ITextResource, ITextResourcesWithLanguage } from 'app-shared/types/global'; import { TextResource, TextResourceProps } from './TextResource'; -import { - queryClientMock, - renderHookWithMockStore, - renderWithMockStore, -} from '../testing/mocks'; +import { queryClientMock, renderHookWithMockStore, renderWithMockStore } from '../testing/mocks'; import { useLayoutSchemaQuery } from '../hooks/queries/useLayoutSchemaQuery'; import { act, screen, waitFor } from '@testing-library/react'; import { textMock } from '../../../../testing/mocks/i18nMock'; @@ -156,7 +152,11 @@ describe('TextResource', () => { it('Calls handleIdChange when selection in search section is changed', async () => { await renderAndOpenSearchSection(); - await act(() => user.click(screen.getByRole('combobox', { name: textMock('ux_editor.search_text_resources_label') }))); + await act(() => + user.click( + screen.getByRole('combobox', { name: textMock('ux_editor.search_text_resources_label') }), + ), + ); await act(() => user.click(screen.getByRole('option', { name: textResources[1].id }))); expect(handleIdChange).toHaveBeenCalledTimes(1); expect(handleIdChange).toHaveBeenCalledWith(textResources[1].id); @@ -164,15 +164,25 @@ describe('TextResource', () => { it('Calls handleIdChange with undefined when "none" is selected', async () => { await renderAndOpenSearchSection(); - await act(() => user.click(screen.getByRole('combobox', { name: textMock('ux_editor.search_text_resources_label') }))); - await act(() => user.click(screen.getByRole('option', { name: textMock('ux_editor.search_text_resources_none') }))); + await act(() => + user.click( + screen.getByRole('combobox', { name: textMock('ux_editor.search_text_resources_label') }), + ), + ); + await act(() => + user.click( + screen.getByRole('option', { name: textMock('ux_editor.search_text_resources_none') }), + ), + ); expect(handleIdChange).toHaveBeenCalledTimes(1); expect(handleIdChange).toHaveBeenCalledWith(undefined); }); it('Closes search section when close button is clicked', async () => { await renderAndOpenSearchSection(); - await act(() => user.click(screen.getByLabelText(textMock('ux_editor.search_text_resources_close')))); + await act(() => + user.click(screen.getByLabelText(textMock('ux_editor.search_text_resources_close'))), + ); expect(screen.queryByRole('combobox')).not.toBeInTheDocument(); }); @@ -180,14 +190,22 @@ describe('TextResource', () => { await render({ textResourceId: 'test', handleRemoveTextResource: jest.fn() }); await act(() => user.click(screen.getByRole('button', { name: textMock('general.delete') }))); expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect(screen.getByText(textMock('ux_editor.text_resource_bindings.delete_confirm'))).toBeInTheDocument(); + expect( + screen.getByText(textMock('ux_editor.text_resource_bindings.delete_confirm')), + ).toBeInTheDocument(); }); it('Calls handleRemoveTextResourceBinding is called when confirm delete button is clicked', async () => { const handleRemoveTextResource = jest.fn(); await render({ handleRemoveTextResource, textResourceId: 'test' }); await act(() => user.click(screen.getByRole('button', { name: textMock('general.delete') }))); - await act(() => user.click(screen.getByRole('button', { name: textMock('ux_editor.text_resource_bindings.delete_confirm') }))); + await act(() => + user.click( + screen.getByRole('button', { + name: textMock('ux_editor.text_resource_bindings.delete_confirm'), + }), + ), + ); expect(handleRemoveTextResource).toBeCalledTimes(1); }); @@ -196,7 +214,7 @@ describe('TextResource', () => { await render({ handleRemoveTextResource, textResourceId: 'test' }); await act(() => user.click(screen.getByRole('button', { name: textMock('general.delete') }))); await act(() => user.click(screen.getByRole('button', { name: textMock('general.cancel') }))); - expect(handleRemoveTextResource).not.toBeCalled(); + expect(handleRemoveTextResource).not.toHaveBeenCalled(); }); it('Renders delete button as disabled when no handleRemoveTextResource is given', async () => { @@ -227,13 +245,19 @@ const renderAndOpenSearchSection = async () => { }; const waitForData = async (resources: ITextResource[]) => { - const { result } = renderHookWithMockStore({}, { - getTextResources: jest.fn().mockImplementation(() => Promise.resolve({ - language: DEFAULT_LANGUAGE, - resources, - })), - })(() => useTextResourcesQuery(org, app)).renderHookResult; - const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()).renderHookResult.result; + const { result } = renderHookWithMockStore( + {}, + { + getTextResources: jest.fn().mockImplementation(() => + Promise.resolve({ + language: DEFAULT_LANGUAGE, + resources, + }), + ), + }, + )(() => useTextResourcesQuery(org, app)).renderHookResult; + const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) + .renderHookResult.result; await waitFor(() => expect(result.current.isSuccess).toBe(true)); await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx index 835887d55bc..35fda2dfb00 100644 --- a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx @@ -4,12 +4,8 @@ import type { ITextResourcesState } from '../features/appData/textResources/text import type { ITextResources, ITextResourcesWithLanguage } from 'app-shared/types/global'; import userEvent from '@testing-library/user-event'; import { TextResourceEdit } from './TextResourceEdit'; -import { - renderHookWithMockStore, - renderWithMockStore, - queriesMock, - queryClientMock, -} from '../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore, renderWithMockStore, queryClientMock } from '../testing/mocks'; import { appDataMock, textResourcesMock } from '../testing/stateMocks'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import { mockUseTranslation } from '../../../../testing/mocks/i18nMock'; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx index d77e2ee2604..83102c5eff7 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/DesignView.test.tsx @@ -7,7 +7,7 @@ import { FormContextProvider } from '../FormContext'; import { DragAndDrop } from 'app-shared/components/dragAndDrop'; import { BASE_CONTAINER_ID } from 'app-shared/constants'; import userEvent from '@testing-library/user-event'; -import { queriesMock } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; import { typedLocalStorage } from 'app-shared/utils/webStorage'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { QueryKey } from 'app-shared/types/QueryKey'; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx index 81b7aa385a2..25737013d17 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx @@ -3,11 +3,8 @@ import { act, screen, waitFor } from '@testing-library/react'; import { NavigationMenu, NavigationMenuProps } from './NavigationMenu'; import userEvent from '@testing-library/user-event'; import { textMock } from '../../../../../../../testing/mocks/i18nMock'; -import { - queriesMock, - renderHookWithMockStore, - renderWithMockStore, -} from '../../../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore, renderWithMockStore } from '../../../../testing/mocks'; import { formDesignerMock } from '../../../../testing/stateMocks'; import { useFormLayoutSettingsQuery } from '../../../../hooks/queries/useFormLayoutSettingsQuery'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddAppAttachmentMetadataMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddAppAttachmentMetadataMutation.test.ts index a1419905daa..8b003093384 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddAppAttachmentMetadataMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddAppAttachmentMetadataMutation.test.ts @@ -1,5 +1,6 @@ import { useAddAppAttachmentMetadataMutation } from './useAddAppAttachmentMetadataMutation'; -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { ApplicationAttachmentMetadata } from 'app-shared/types/ApplicationAttachmentMetadata'; // Test data: @@ -11,22 +12,18 @@ const metadata: ApplicationAttachmentMetadata = { maxCount: 3, minCount: 1, maxSize: 16, - fileType: 'jpg' + fileType: 'jpg', }; describe('useAddAppAttachmentMetadataMutation', () => { it('Calls addAppAttachmentMetadata with correct arguments and payload', async () => { - const metadataResult = renderHookWithMockStore()(() => useAddAppAttachmentMetadataMutation(org, app)) - .renderHookResult - .result; + const metadataResult = renderHookWithMockStore()(() => + useAddAppAttachmentMetadataMutation(org, app), + ).renderHookResult.result; await metadataResult.current.mutateAsync(metadata); expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledTimes(1); - expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith( - org, - app, - metadata - ); + expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith(org, app, metadata); }); }); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddFormContainerMutation.test.ts index 55f8bd1e35f..e99b176cf9c 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddFormContainerMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { waitFor } from '@testing-library/react'; import { diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts index 930b9ac5e21..634b88118b5 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts @@ -1,4 +1,5 @@ -import { queryClientMock, queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; import { appStateMock, formDesignerMock } from '../../testing/stateMocks'; import { waitFor } from '@testing-library/react'; import { AddFormItemMutationArgs, useAddItemToLayoutMutation } from './useAddItemToLayoutMutation'; @@ -28,8 +29,8 @@ const appStateMockCopy = (layoutSetName: string): Partial => ({ layout: { ...formDesignerMock.layout, selectedLayoutSet: layoutSetName, - } - } + }, + }, }); const applicationAttachmentMetaDataMock: ApplicationAttachmentMetadata = { @@ -42,7 +43,6 @@ const applicationAttachmentMetaDataMock: ApplicationAttachmentMetadata = { }; describe('useAddItemToLayoutMutation', () => { - afterEach(jest.clearAllMocks); it('Returns ID of new item', async () => { @@ -77,27 +77,33 @@ describe('useAddItemToLayoutMutation', () => { const { result } = renderAddItemToLayoutMutation('test-layout-set-2'); result.current.mutate({ ...defaultArgs, componentType: ComponentType.FileUpload }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); - expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith(org, app, { ...applicationAttachmentMetaDataMock, taskId: 'Task_2' }); + expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith(org, app, { + ...applicationAttachmentMetaDataMock, + taskId: 'Task_2', + }); }); it('Adds Task_1 to attachment metadata when component type is fileUpload and selectedLayoutSet is undefined', async () => { const { result } = renderAddItemToLayoutMutation(undefined); result.current.mutate({ ...defaultArgs, componentType: ComponentType.FileUpload }); await waitFor(() => expect(result.current.isSuccess).toBe(true)); - expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith(org, app, { ...applicationAttachmentMetaDataMock, taskId: 'Task_1' }); + expect(queriesMock.addAppAttachmentMetadata).toHaveBeenCalledWith(org, app, { + ...applicationAttachmentMetaDataMock, + taskId: 'Task_1', + }); }); }); const renderAddItemToLayoutMutation = (layoutSetName?: string) => { queryClientMock.setQueryData( [QueryKey.FormLayouts, org, app, layoutSetName], - convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts + convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts, ); queryClientMock.setQueryData( [QueryKey.LayoutSets, org, app], - layoutSetName ? layoutSetsMock : null + layoutSetName ? layoutSetsMock : null, ); - return renderHookWithMockStore(appStateMockCopy(layoutSetName))( - () => useAddItemToLayoutMutation(org, app, layoutSetName) + return renderHookWithMockStore(appStateMockCopy(layoutSetName))(() => + useAddItemToLayoutMutation(org, app, layoutSetName), ).renderHookResult; -} +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts index fa6e6b17cbb..dd48d39139c 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; import { AddLayoutMutationArgs, useAddLayoutMutation } from './useAddLayoutMutation'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { waitFor } from '@testing-library/react'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddWidgetMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddWidgetMutation.test.ts index 2acdddba6c5..e9d083d4fc8 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddWidgetMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddWidgetMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { waitFor } from '@testing-library/react'; import { AddWidgetMutationArgs, useAddWidgetMutation } from './useAddWidgetMutation'; @@ -21,7 +22,7 @@ const widget: IWidget = { components: [], texts, displayName, -} +}; const defaultArgs: AddWidgetMutationArgs = { widget, position: 0 }; describe('useAddWidgetMutation', () => { @@ -37,14 +38,21 @@ describe('useAddWidgetMutation', () => { const { result } = await renderAddWidgetMutation(); await result.current.mutateAsync(defaultArgs); expect(queriesMock.upsertTextResources).toHaveBeenCalledTimes(texts.length); - expect(queriesMock.upsertTextResources).toHaveBeenCalledWith(org, app, language, { [textId]: textValue }); + expect(queriesMock.upsertTextResources).toHaveBeenCalledWith(org, app, language, { + [textId]: textValue, + }); }); }); const renderAddWidgetMutation = async () => { - const { result: formLayouts } = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult; + const { result: formLayouts } = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult; await waitFor(() => expect(formLayouts.current.isSuccess).toBe(true)); - const { result: texts } = renderHookWithMockStore()(() => useTextResourcesQuery(org, app)).renderHookResult; + const { result: texts } = renderHookWithMockStore()(() => + useTextResourcesQuery(org, app), + ).renderHookResult; await waitFor(() => expect(texts.current.isSuccess).toBe(true)); - return renderHookWithMockStore()(() => useAddWidgetMutation(org, app, selectedLayoutSet)).renderHookResult; -} + return renderHookWithMockStore()(() => useAddWidgetMutation(org, app, selectedLayoutSet)) + .renderHookResult; +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useConfigureLayoutSetMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useConfigureLayoutSetMutation.test.ts index eb907050471..cc263f88869 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useConfigureLayoutSetMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useConfigureLayoutSetMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useConfigureLayoutSetMutation } from './useConfigureLayoutSetMutation'; import { waitFor } from '@testing-library/react'; @@ -8,14 +9,14 @@ const app = 'app'; const layoutSetName = 'first-layout-set-name'; describe('useConfigureLayoutSetMutation', () => { - it('Calls configureLayoutSet with correct arguments and payload', async () => { - const configureLayoutSetResult = renderHookWithMockStore()(() => useConfigureLayoutSetMutation(org, app)) - .renderHookResult - .result; - await configureLayoutSetResult.current.mutateAsync({ layoutSetName }); - await waitFor(() => expect(configureLayoutSetResult.current.isSuccess).toBe(true)); - - expect(queriesMock.configureLayoutSet).toHaveBeenCalledTimes(1); - expect(queriesMock.configureLayoutSet).toHaveBeenCalledWith(org, app, layoutSetName); - }); -}); \ No newline at end of file + it('Calls configureLayoutSet with correct arguments and payload', async () => { + const configureLayoutSetResult = renderHookWithMockStore()(() => + useConfigureLayoutSetMutation(org, app), + ).renderHookResult.result; + await configureLayoutSetResult.current.mutateAsync({ layoutSetName }); + await waitFor(() => expect(configureLayoutSetResult.current.isSuccess).toBe(true)); + + expect(queriesMock.configureLayoutSet).toHaveBeenCalledTimes(1); + expect(queriesMock.configureLayoutSet).toHaveBeenCalledWith(org, app, layoutSetName); + }); +}); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteAppAttachmentMetadataMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteAppAttachmentMetadataMutation.test.ts index 302004030f0..8eecc126f60 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteAppAttachmentMetadataMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteAppAttachmentMetadataMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useDeleteAppAttachmentMetadataMutation } from './useDeleteAppAttachmentMetadataMutation'; // Test data: @@ -8,9 +9,9 @@ const id = 'test'; describe('useDeleteAppAttachmentMetadataMutation', () => { it('Calls deleteAppAttachmentMetadata with correct arguments and payload', async () => { - const metadataResult = renderHookWithMockStore()(() => useDeleteAppAttachmentMetadataMutation(org, app)) - .renderHookResult - .result; + const metadataResult = renderHookWithMockStore()(() => + useDeleteAppAttachmentMetadataMutation(org, app), + ).renderHookResult.result; await metadataResult.current.mutateAsync(id); expect(queriesMock.deleteAppAttachmentMetadata).toHaveBeenCalledTimes(1); expect(queriesMock.deleteAppAttachmentMetadata).toHaveBeenCalledWith(org, app, id); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormComponentMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormComponentMutation.test.ts index c29d7257e36..684f1675368 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormComponentMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormComponentMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { waitFor } from '@testing-library/react'; import { useDeleteFormComponentMutation } from './useDeleteFormComponentMutation'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; @@ -21,17 +22,19 @@ describe('useDeleteFormComponentMutation', () => { selectedLayoutSet, expect.objectContaining({ data: expect.objectContaining({ - layout: expect.not.arrayContaining([ - expect.objectContaining({ id: component2IdMock }) - ]) - }) - }) + layout: expect.not.arrayContaining([expect.objectContaining({ id: component2IdMock })]), + }), + }), ); }); }); const renderDeleteFormComponentsMutation = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const formLayoutsResult = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); - return renderHookWithMockStore()(() => useDeleteFormComponentMutation(org, app, selectedLayoutSet)).renderHookResult; -} + return renderHookWithMockStore()(() => + useDeleteFormComponentMutation(org, app, selectedLayoutSet), + ).renderHookResult; +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts index 6be0443f953..1ef4b3d4f79 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { waitFor } from '@testing-library/react'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useDeleteFormContainerMutation } from './useDeleteFormContainerMutation'; @@ -22,18 +23,19 @@ describe('useDeleteFormContainerMutation', () => { selectedLayoutSet, expect.objectContaining({ data: expect.objectContaining({ - layout: expect.not.arrayContaining([ - expect.objectContaining({ id }) - ]) - }) - }) + layout: expect.not.arrayContaining([expect.objectContaining({ id })]), + }), + }), ); }); }); - const renderDeleteFormContainerMutation = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const formLayoutsResult = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); - return renderHookWithMockStore()(() => useDeleteFormContainerMutation(org, app, selectedLayoutSet)).renderHookResult; -} + return renderHookWithMockStore()(() => + useDeleteFormContainerMutation(org, app, selectedLayoutSet), + ).renderHookResult; +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts index 7e8f804a674..3b1b2b5bf89 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts @@ -1,8 +1,13 @@ -import { queriesMock, formLayoutSettingsMock, renderHookWithMockStore, queryClientMock } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + queryClientMock, +} from '../../testing/mocks'; import { useDeleteLayoutMutation } from './useDeleteLayoutMutation'; import { externalLayoutsMock, layout2NameMock } from '../../testing/layoutMock'; -import { QueryKey } from "app-shared/types/QueryKey"; -import { convertExternalLayoutsToInternalFormat } from "../../utils/formLayoutsUtils"; +import { QueryKey } from 'app-shared/types/QueryKey'; +import { convertExternalLayoutsToInternalFormat } from '../../utils/formLayoutsUtils'; // Test data: const org = 'org'; @@ -17,20 +22,40 @@ describe('useDeleteLayoutMutation', () => { const { result } = renderDeleteLayoutMutation(); await result.current.mutateAsync(layoutName); expect(queriesMock.deleteFormLayout).toHaveBeenCalledTimes(1); - expect(queriesMock.deleteFormLayout).toHaveBeenCalledWith(org, app, layoutName, selectedLayoutSet); + expect(queriesMock.deleteFormLayout).toHaveBeenCalledWith( + org, + app, + layoutName, + selectedLayoutSet, + ); }); it('Calls deleteFormLayout with the name of the receipt layout when deleting custom receipt', async () => { const { result } = renderDeleteLayoutMutation(); await result.current.mutateAsync(formLayoutSettingsMock.receiptLayoutName); expect(queriesMock.deleteFormLayout).toHaveBeenCalledTimes(1); - expect(queriesMock.deleteFormLayout).toHaveBeenCalledWith(org, app, formLayoutSettingsMock.receiptLayoutName, selectedLayoutSet); - expect(queriesMock.saveFormLayoutSettings).toHaveBeenCalledWith(org, app, selectedLayoutSet, { ...formLayoutSettingsMock, receiptLayoutName: undefined }); + expect(queriesMock.deleteFormLayout).toHaveBeenCalledWith( + org, + app, + formLayoutSettingsMock.receiptLayoutName, + selectedLayoutSet, + ); + expect(queriesMock.saveFormLayoutSettings).toHaveBeenCalledWith(org, app, selectedLayoutSet, { + ...formLayoutSettingsMock, + receiptLayoutName: undefined, + }); }); }); const renderDeleteLayoutMutation = () => { - queryClientMock.setQueryData([QueryKey.FormLayouts, org, app, selectedLayoutSet], convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts); - queryClientMock.setQueryData([QueryKey.FormLayoutSettings, org, app, selectedLayoutSet], formLayoutSettingsMock); - return renderHookWithMockStore()(() => useDeleteLayoutMutation(org, app, selectedLayoutSet)).renderHookResult; -} + queryClientMock.setQueryData( + [QueryKey.FormLayouts, org, app, selectedLayoutSet], + convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts, + ); + queryClientMock.setQueryData( + [QueryKey.FormLayoutSettings, org, app, selectedLayoutSet], + formLayoutSettingsMock, + ); + return renderHookWithMockStore()(() => useDeleteLayoutMutation(org, app, selectedLayoutSet)) + .renderHookResult; +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx index d2975d2936b..0d56fff6918 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx +++ b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx @@ -1,4 +1,5 @@ -import { queriesMock, queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutMutation } from './useFormLayoutMutation'; import { IInternalLayout } from '../../types/global'; import { ComponentType } from 'app-shared/types/ComponentType'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutSettingsMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutSettingsMutation.test.ts index 6a4e055cf9b..5e72e54af57 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutSettingsMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutSettingsMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutSettingsMutation } from './useFormLayoutSettingsMutation'; import { waitFor } from '@testing-library/react'; @@ -9,9 +10,9 @@ const selectedLayoutSet = 'test-layout-set'; describe('useFormLayoutSettingsMutation', () => { it('Calls saveFormLayoutSettings with correct arguments and payload', async () => { - const settingsResult = renderHookWithMockStore()(() => useFormLayoutSettingsMutation(org, app, selectedLayoutSet)) - .renderHookResult - .result; + const settingsResult = renderHookWithMockStore()(() => + useFormLayoutSettingsMutation(org, app, selectedLayoutSet), + ).renderHookResult.result; settingsResult.current.mutate(formLayoutSettingsMock); await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); @@ -21,7 +22,7 @@ describe('useFormLayoutSettingsMutation', () => { org, app, selectedLayoutSet, - formLayoutSettingsMock + formLayoutSettingsMock, ); }); }); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useRuleConfigMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useRuleConfigMutation.test.ts index 543da2094a1..33662aa8584 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useRuleConfigMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useRuleConfigMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useRuleConfigMutation } from './useRuleConfigMutation'; import { RuleConfig } from 'app-shared/types/RuleConfig'; @@ -12,11 +13,11 @@ const newRuleConfig: RuleConfig = { ruleConnection1: { selectedFunction: 'selectedFunction1', inputParams: {}, - outParams: {} - } + outParams: {}, + }, }, - conditionalRendering: {} - } + conditionalRendering: {}, + }, }; describe('useRuleConfigMutation', () => { @@ -26,8 +27,15 @@ describe('useRuleConfigMutation', () => { const { result } = await render(); await result.current.mutateAsync(newRuleConfig); expect(queriesMock.saveRuleConfig).toHaveBeenCalledTimes(1); - expect(queriesMock.saveRuleConfig).toHaveBeenCalledWith(org, app, selectedLayoutSet, newRuleConfig); + expect(queriesMock.saveRuleConfig).toHaveBeenCalledWith( + org, + app, + selectedLayoutSet, + newRuleConfig, + ); }); }); -const render = async () => renderHookWithMockStore()(() => useRuleConfigMutation(org, app, selectedLayoutSet)).renderHookResult; +const render = async () => + renderHookWithMockStore()(() => useRuleConfigMutation(org, app, selectedLayoutSet)) + .renderHookResult; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateAppAttachmentMetadataMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateAppAttachmentMetadataMutation.test.ts index 105adf4f831..a2889843856 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateAppAttachmentMetadataMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateAppAttachmentMetadataMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useUpdateAppAttachmentMetadataMutation } from './useUpdateAppAttachmentMetadataMutation'; import { ApplicationAttachmentMetadata } from 'app-shared/types/ApplicationAttachmentMetadata'; @@ -8,9 +9,9 @@ const app = 'app'; describe('useUpdateAppAttachmentMetadataMutation', () => { it('Calls updateAppAttachmentMetadata with correct arguments and payload', async () => { - const metadataResult = renderHookWithMockStore()(() => useUpdateAppAttachmentMetadataMutation(org, app)) - .renderHookResult - .result; + const metadataResult = renderHookWithMockStore()(() => + useUpdateAppAttachmentMetadataMutation(org, app), + ).renderHookResult.result; const metadata: ApplicationAttachmentMetadata = { id: 'test', @@ -18,15 +19,11 @@ describe('useUpdateAppAttachmentMetadataMutation', () => { maxCount: 3, minCount: 1, maxSize: 16, - fileType: 'jpg' + fileType: 'jpg', }; await metadataResult.current.mutateAsync(metadata); expect(queriesMock.updateAppAttachmentMetadata).toHaveBeenCalledTimes(1); - expect(queriesMock.updateAppAttachmentMetadata).toHaveBeenCalledWith( - org, - app, - metadata - ); + expect(queriesMock.updateAppAttachmentMetadata).toHaveBeenCalledWith(org, app, metadata); }); }); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts index 93f74bb69e3..4a38a146f65 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts @@ -1,11 +1,16 @@ -import { queriesMock, queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; import { ComponentType } from 'app-shared/types/ComponentType'; -import { UpdateFormComponentMutationArgs, useUpdateFormComponentMutation } from './useUpdateFormComponentMutation'; +import { + UpdateFormComponentMutationArgs, + useUpdateFormComponentMutation, +} from './useUpdateFormComponentMutation'; import { component1IdMock, externalLayoutsMock, layout1NameMock } from '../../testing/layoutMock'; import type { FormCheckboxesComponent, FormComponent, - FormFileUploaderComponent, FormRadioButtonsComponent, + FormFileUploaderComponent, + FormRadioButtonsComponent, } from '../../types/FormComponent'; import { IDataModelBindings } from '../../types/global'; import { QueryKey } from 'app-shared/types/QueryKey'; @@ -25,7 +30,7 @@ const updatedComponent: FormComponent = { itemType: 'COMPONENT', type: ComponentType.TextArea, dataModelBindings, -} +}; const defaultArgs: UpdateFormComponentMutationArgs = { id, updatedComponent }; describe('useUpdateFormComponentMutation', () => { @@ -34,9 +39,9 @@ describe('useUpdateFormComponentMutation', () => { it('Saves layout with updated component', async () => { renderAndWaitForData(); - const updateFormComponentResult = renderHookWithMockStore()(() => useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet)) - .renderHookResult - .result; + const updateFormComponentResult = renderHookWithMockStore()(() => + useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet), + ).renderHookResult.result; await updateFormComponentResult.current.mutateAsync(defaultArgs); @@ -53,18 +58,18 @@ describe('useUpdateFormComponentMutation', () => { id, type, dataModelBindings, - } - ]) - }) - }) + }, + ]), + }), + }), ); }); it('Does not run attachment metadata queries if the component type is not fileUpload', async () => { renderAndWaitForData(); - const updateFormComponentResult = renderHookWithMockStore()(() => useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet)) - .renderHookResult - .result; + const updateFormComponentResult = renderHookWithMockStore()(() => + useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet), + ).renderHookResult.result; await updateFormComponentResult.current.mutateAsync(defaultArgs); expect(queriesMock.addAppAttachmentMetadata).not.toHaveBeenCalled(); expect(queriesMock.deleteAppAttachmentMetadata).not.toHaveBeenCalled(); @@ -73,9 +78,9 @@ describe('useUpdateFormComponentMutation', () => { it('Updates attachment metadata queries if the component type is fileUpload', async () => { renderAndWaitForData(); - const updateFormComponentResult = renderHookWithMockStore()(() => useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet)) - .renderHookResult - .result; + const updateFormComponentResult = renderHookWithMockStore()(() => + useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet), + ).renderHookResult.result; const newComponent: FormFileUploaderComponent = { ...updatedComponent, description: 'test', @@ -89,16 +94,16 @@ describe('useUpdateFormComponentMutation', () => { const args: UpdateFormComponentMutationArgs = { ...defaultArgs, updatedComponent: newComponent, - } + }; await updateFormComponentResult.current.mutateAsync(args); expect(queriesMock.updateAppAttachmentMetadata).toHaveBeenCalledTimes(1); }); it('Does not keep original optionsId and options props from component when updating RadioButtons and CheckBoxes', async () => { renderAndWaitForData(); - const updateFormComponentResult = renderHookWithMockStore()(() => useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet)) - .renderHookResult - .result; + const updateFormComponentResult = renderHookWithMockStore()(() => + useUpdateFormComponentMutation(org, app, selectedLayoutName, selectedLayoutSet), + ).renderHookResult.result; for (const componentType of [ComponentType.RadioButtons, ComponentType.Checkboxes]) { for (const optionKind of ['options', 'optionsId']) { @@ -112,7 +117,7 @@ describe('useUpdateFormComponentMutation', () => { const args: UpdateFormComponentMutationArgs = { ...defaultArgs, updatedComponent: newComponent, - } + }; await updateFormComponentResult.current.mutateAsync(args); expect(queriesMock.saveFormLayout).toHaveBeenCalledWith( org, @@ -127,25 +132,20 @@ describe('useUpdateFormComponentMutation', () => { type: componentType, dataModelBindings, ...optionsProp, - } - ]) - }) - }) + }, + ]), + }), + }), ); } } - - }); }); const renderAndWaitForData = () => { queryClientMock.setQueryData( [QueryKey.FormLayouts, org, app, selectedLayoutSet], - convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts - ); - queryClientMock.setQueryData( - [QueryKey.RuleConfig, org, app, selectedLayoutSet], - ruleConfigMock + convertExternalLayoutsToInternalFormat(externalLayoutsMock).convertedLayouts, ); + queryClientMock.setQueryData([QueryKey.RuleConfig, org, app, selectedLayoutSet], ruleConfigMock); }; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts index 8a4c8469046..06ba4b3c030 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { waitFor } from '@testing-library/react'; import { useUpdateFormComponentOrderMutation } from './useUpdateFormComponentOrderMutation'; @@ -8,7 +9,7 @@ import { component2IdMock, container1IdMock, layout1NameMock, - layoutMock + layoutMock, } from '../../testing/layoutMock'; // Test data: @@ -22,13 +23,13 @@ describe('useUpdateFormComponentOrderMutation', () => { it('Calls updateFormComponentOrder with correct arguments and payload', async () => { await renderAndWaitForData(); - const componentOrderResult = renderHookWithMockStore()(() => useUpdateFormComponentOrderMutation(org, app, selectedLayoutSet)) - .renderHookResult - .result; + const componentOrderResult = renderHookWithMockStore()(() => + useUpdateFormComponentOrderMutation(org, app, selectedLayoutSet), + ).renderHookResult.result; const newOrder: IFormLayoutOrder = { ...layoutMock.order, - [container1IdMock]: [component2IdMock, component1IdMock] + [container1IdMock]: [component2IdMock, component1IdMock], }; await componentOrderResult.current.mutateAsync(newOrder); @@ -44,14 +45,16 @@ describe('useUpdateFormComponentOrderMutation', () => { expect.objectContaining({ id: container1IdMock }), expect.objectContaining({ id: component2IdMock }), expect.objectContaining({ id: component1IdMock }), - ] - }) - }) + ], + }), + }), ); }); }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const formLayoutsResult = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); -} +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts index 9cbb0aa7f8c..8b8c3245e83 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts @@ -1,8 +1,12 @@ import { waitFor } from '@testing-library/react'; -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useRuleConfigQuery } from '../queries/useRuleConfigQuery'; -import { UpdateFormContainerMutationArgs, useUpdateFormContainerMutation } from './useUpdateFormContainerMutation'; +import { + UpdateFormContainerMutationArgs, + useUpdateFormContainerMutation, +} from './useUpdateFormContainerMutation'; import { FormContainer } from '../../types/FormContainer'; import { container1IdMock, layout1Mock, layout1NameMock } from '../../testing/layoutMock'; @@ -24,9 +28,9 @@ describe('useUpdateFormContainerMutation', () => { it('Saves layouts with new container and updates rule config', async () => { await renderAndWaitForData(); - const updateFormContainerResult = renderHookWithMockStore()(() => useUpdateFormContainerMutation(org, app, selectedLayoutName, selectedLayoutSet)) - .renderHookResult - .result; + const updateFormContainerResult = renderHookWithMockStore()(() => + useUpdateFormContainerMutation(org, app, selectedLayoutName, selectedLayoutSet), + ).renderHookResult.result; await updateFormContainerResult.current.mutateAsync(mutationArgs); @@ -43,17 +47,21 @@ describe('useUpdateFormContainerMutation', () => { ...layout1Mock.data.layout[0], id: updatedContainer.id, maxCount, - } - ]) - }) - }) + }, + ]), + }), + }), ); }); }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; - const ruleConfigResult = renderHookWithMockStore()(() => useRuleConfigQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const formLayoutsResult = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; + const ruleConfigResult = renderHookWithMockStore()(() => + useRuleConfigQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(ruleConfigResult.current.isSuccess).toBe(true)); -} +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts index a2bfbe2faba..9857d2e6f97 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts @@ -1,8 +1,12 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { waitFor } from '@testing-library/react'; -import { UpdateLayoutNameMutationArgs, useUpdateLayoutNameMutation } from './useUpdateLayoutNameMutation'; +import { + UpdateLayoutNameMutationArgs, + useUpdateLayoutNameMutation, +} from './useUpdateLayoutNameMutation'; import { layout1NameMock } from '../../testing/layoutMock'; // Test data: @@ -19,20 +23,30 @@ describe('useUpdateLayoutNameMutation', () => { it('Updates layout name', async () => { await renderAndWaitForData(); - const updateLayoutNameResult = renderHookWithMockStore()(() => useUpdateLayoutNameMutation(org, app, selectedLayoutSet)) - .renderHookResult - .result; + const updateLayoutNameResult = renderHookWithMockStore()(() => + useUpdateLayoutNameMutation(org, app, selectedLayoutSet), + ).renderHookResult.result; await updateLayoutNameResult.current.mutateAsync(args); expect(queriesMock.updateFormLayoutName).toHaveBeenCalledTimes(1); - expect(queriesMock.updateFormLayoutName).toHaveBeenCalledWith(org, app, oldName, newName, selectedLayoutSet); + expect(queriesMock.updateFormLayoutName).toHaveBeenCalledWith( + org, + app, + oldName, + newName, + selectedLayoutSet, + ); }); }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; - const settingsResult = renderHookWithMockStore()(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const formLayoutsResult = renderHookWithMockStore()(() => + useFormLayoutsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; + const settingsResult = renderHookWithMockStore()(() => + useFormLayoutSettingsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); -} +}; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts index 2556f89abc8..6fc91b3df3e 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts @@ -1,7 +1,11 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { waitFor } from '@testing-library/react'; -import { UpdateLayoutOrderMutationArgs, useUpdateLayoutOrderMutation } from './useUpdateLayoutOrderMutation'; +import { + UpdateLayoutOrderMutationArgs, + useUpdateLayoutOrderMutation, +} from './useUpdateLayoutOrderMutation'; import { layout1NameMock, layout2NameMock } from '../../testing/layoutMock'; // Test data: @@ -15,13 +19,13 @@ describe('useUpdateLayoutOrderMutation', () => { it('Moves layout down when direction is set to "down"', async () => { await renderAndWaitForData(); - const updateLayoutOrderResult = renderHookWithMockStore()(() => useUpdateLayoutOrderMutation(org, app, selectedLayoutSet)) - .renderHookResult - .result; + const updateLayoutOrderResult = renderHookWithMockStore()(() => + useUpdateLayoutOrderMutation(org, app, selectedLayoutSet), + ).renderHookResult.result; const args: UpdateLayoutOrderMutationArgs = { layoutName: layout1NameMock, - direction: 'down' + direction: 'down', }; await updateLayoutOrderResult.current.mutateAsync(args); @@ -32,22 +36,22 @@ describe('useUpdateLayoutOrderMutation', () => { selectedLayoutSet, expect.objectContaining({ pages: expect.objectContaining({ - order: [layout2NameMock, layout1NameMock] - }) - }) + order: [layout2NameMock, layout1NameMock], + }), + }), ); }); it('Moves layout up when direction is set to "up"', async () => { await renderAndWaitForData(); - const updateLayoutOrderResult = renderHookWithMockStore()(() => useUpdateLayoutOrderMutation(org, app, selectedLayoutSet)) - .renderHookResult - .result; + const updateLayoutOrderResult = renderHookWithMockStore()(() => + useUpdateLayoutOrderMutation(org, app, selectedLayoutSet), + ).renderHookResult.result; const args: UpdateLayoutOrderMutationArgs = { layoutName: layout2NameMock, - direction: 'up' + direction: 'up', }; await updateLayoutOrderResult.current.mutateAsync(args); @@ -58,14 +62,16 @@ describe('useUpdateLayoutOrderMutation', () => { selectedLayoutSet, expect.objectContaining({ pages: expect.objectContaining({ - order: [layout2NameMock, layout1NameMock] - }) - }) + order: [layout2NameMock, layout1NameMock], + }), + }), ); }); }); const renderAndWaitForData = async () => { - const settingsResult = renderHookWithMockStore()(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const settingsResult = renderHookWithMockStore()(() => + useFormLayoutSettingsQuery(org, app, selectedLayoutSet), + ).renderHookResult.result; await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/queries/useFrontEndSettingsQuery.test.ts b/frontend/packages/ux-editor/src/hooks/queries/useFrontEndSettingsQuery.test.ts index 9bc0c01c029..5ad5a989945 100644 --- a/frontend/packages/ux-editor/src/hooks/queries/useFrontEndSettingsQuery.test.ts +++ b/frontend/packages/ux-editor/src/hooks/queries/useFrontEndSettingsQuery.test.ts @@ -1,5 +1,6 @@ import { waitFor } from '@testing-library/react'; -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFrontEndSettingsQuery } from './useFrontEndSettingsQuery'; // Test data: diff --git a/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts b/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts index d9a11e720ca..7b03aa6d974 100644 --- a/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts +++ b/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts @@ -1,4 +1,5 @@ -import { queriesMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { waitFor } from '@testing-library/react'; import { useRuleModelQuery } from './useRuleModelQuery'; import { @@ -42,39 +43,41 @@ describe('useRuleModelQuery', () => { name: rule1Name, inputs: { [rule1Input1Name]: rule1Input1Label, - [rule1Input2Name]: rule1Input2Label + [rule1Input2Name]: rule1Input2Label, }, - type: 'rule' + type: 'rule', }, { name: rule2Name, inputs: { [rule2Input1Name]: rule2Input1Label, - [rule2Input2Name]: rule2Input2Label + [rule2Input2Name]: rule2Input2Label, }, - type: 'rule' + type: 'rule', }, { name: condition1Name, inputs: { [condition1Input1Name]: condition1Input1Label }, - type: 'condition' + type: 'condition', }, { name: condition2Name, inputs: { [condition2Input1Name]: condition2Input1Label }, - type: 'condition' + type: 'condition', }, { name: condition3Name, inputs: { [condition3Input1Name]: condition3Input1Label }, - type: 'condition' - } + type: 'condition', + }, ]); }); }); const renderAndWaitForSuccess = async () => { - const { renderHookResult } = renderHookWithMockStore()(() => useRuleModelQuery(org, app, selectedLayoutSet)); + const { renderHookResult } = renderHookWithMockStore()(() => + useRuleModelQuery(org, app, selectedLayoutSet), + ); await waitFor(() => expect(renderHookResult.result.current.isSuccess).toBe(true)); return renderHookResult; }; diff --git a/frontend/packages/ux-editor/src/testing/mocks.tsx b/frontend/packages/ux-editor/src/testing/mocks.tsx index b7afb0e9723..cb2dc5a62a7 100644 --- a/frontend/packages/ux-editor/src/testing/mocks.tsx +++ b/frontend/packages/ux-editor/src/testing/mocks.tsx @@ -7,25 +7,13 @@ import { render, renderHook } from '@testing-library/react'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { ILayoutSettings } from 'app-shared/types/global'; import { BrowserRouter } from 'react-router-dom'; -import ruleHandlerMock from './ruleHandlerMock'; import { PreviewConnectionContextProvider } from 'app-shared/providers/PreviewConnectionContext'; -import { ruleConfig as ruleConfigMock } from './ruleConfigMock'; -import { - externalLayoutsMock, - layout1NameMock, - layout2NameMock, - layoutSetsMock, -} from './layoutMock'; +import { layout1NameMock, layout2NameMock } from './layoutMock'; import { appStateMock } from './stateMocks'; -import { queriesMock as allQueriesMock } from 'app-shared/mocks/queriesMock'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; import { QueryClient } from '@tanstack/react-query'; -import expressionSchema from './schemas/json/layout/expression.schema.v1.json'; -import numberFormatSchema from './schemas/json/layout/number-format.schema.v1.json'; -import layoutSchema from './schemas/json/layout/layout.schema.v1.json'; import { AppContext, AppContextProps } from '../AppContext'; import { appContextMock } from './appContextMock'; -import inputComponentSchema from './schemas/json/component/Input.schema.v1.json'; -import commonDefsComponentSchema from './schemas/json/component/Input.schema.v1.json'; export const formLayoutSettingsMock: ILayoutSettings = { pages: { @@ -38,27 +26,6 @@ export const textLanguagesMock = ['nb', 'nn', 'en']; export const optionListIdsMock: string[] = ['test-1', 'test-2']; -export const queriesMock: ServicesContextProps = { - ...allQueriesMock, - getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({ elements: {} })), - getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve(expressionSchema)), - getFormLayoutSettings: jest - .fn() - .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), - getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)), - getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve(layoutSchema)), - getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve(layoutSetsMock)), - getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve(numberFormatSchema)), - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), - getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfigMock)), - getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), - getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), - getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve(inputComponentSchema)), - getComponentsCommonDefsSchema: jest - .fn() - .mockImplementation(() => Promise.resolve(commonDefsComponentSchema)), -}; - export const queryClientMock = new QueryClient({ defaultOptions: { queries: { staleTime: Infinity }, From 202d43eafe249baa8db043fda90d85c671b40804 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 19 Dec 2023 11:00:24 +0100 Subject: [PATCH 04/15] Fix EditDataModelBindings tests & cleanup --- .../components/deploy/DeployDropdown.test.tsx | 28 ++- .../dataModelling/DataModelling.test.tsx | 54 ++--- .../LandingPagePanel.test.tsx | 22 +- .../features/textEditor/TextEditor.test.tsx | 43 ++-- .../components/TreeView/SchemaItem.test.tsx | 8 +- .../lib/mutations/ui-schema-reducers.test.ts | 2 +- .../components/AltinnConfirmDialog.test.tsx | 6 +- .../InputActionWrapper.test.tsx | 6 +- .../text-editor/src/RightMenu.test.tsx | 24 +- .../packages/text-editor/src/TextRow.test.tsx | 8 +- .../FormComponent/FormComponent.test.tsx | 12 +- .../src/components/TextResource.test.tsx | 2 +- .../editModal/EditDataModelBindings.test.tsx | 206 ++++++++---------- .../EditTextResourceBinding.test.tsx | 80 ++++--- 14 files changed, 270 insertions(+), 231 deletions(-) diff --git a/frontend/app-development/features/appPublish/components/deploy/DeployDropdown.test.tsx b/frontend/app-development/features/appPublish/components/deploy/DeployDropdown.test.tsx index cfcff42da1a..6f0ff1c2616 100644 --- a/frontend/app-development/features/appPublish/components/deploy/DeployDropdown.test.tsx +++ b/frontend/app-development/features/appPublish/components/deploy/DeployDropdown.test.tsx @@ -16,13 +16,17 @@ describe('DeployDropdown', () => { it('should open the confirmation dialog when clicking the delete button', async () => { await render(); - const deleteButton = screen.getByRole('button', { name: textMock('app_deploy_messages.btn_deploy_new_version') }); + const deleteButton = screen.getByRole('button', { + name: textMock('app_deploy_messages.btn_deploy_new_version'), + }); await act(() => user.click(deleteButton)); const dialog = screen.getByRole('dialog'); expect(dialog).toBeInTheDocument(); - const text = await screen.findByText(textMock('app_deploy_messages.deploy_confirmation_short', { selectedImageTag: '' })); + const text = await screen.findByText( + textMock('app_deploy_messages.deploy_confirmation_short', { selectedImageTag: '' }), + ); expect(text).toBeInTheDocument(); const confirmButton = screen.getByRole('button', { name: textMock('general.yes') }); @@ -35,38 +39,44 @@ describe('DeployDropdown', () => { it('should confirm and close the dialog when clicking the confirm button', async () => { await render(); - const deleteButton = screen.getByRole('button', { name: textMock('app_deploy_messages.btn_deploy_new_version') }); + const deleteButton = screen.getByRole('button', { + name: textMock('app_deploy_messages.btn_deploy_new_version'), + }); await act(() => user.click(deleteButton)); const confirmButton = screen.getByRole('button', { name: textMock('general.yes') }); await act(() => user.click(confirmButton)); - expect(startDeployMock).toBeCalledTimes(1); + expect(startDeployMock).toHaveBeenCalledTimes(1); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); it('should close the confirmation dialog when clicking the cancel button', async () => { await render(); - const deleteButton = screen.getByRole('button', { name: textMock('app_deploy_messages.btn_deploy_new_version') }); + const deleteButton = screen.getByRole('button', { + name: textMock('app_deploy_messages.btn_deploy_new_version'), + }); await act(() => user.click(deleteButton)); const cancelButton = screen.getByRole('button', { name: textMock('general.cancel') }); await act(() => user.click(cancelButton)); - expect(startDeployMock).toBeCalledTimes(0); + expect(startDeployMock).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); it('should close when clicking outside the popover', async () => { await render(); - const deleteButton = screen.getByRole('button', { name: textMock('app_deploy_messages.btn_deploy_new_version') }); + const deleteButton = screen.getByRole('button', { + name: textMock('app_deploy_messages.btn_deploy_new_version'), + }); await act(() => user.click(deleteButton)); await act(() => user.click(document.body)); - expect(startDeployMock).toBeCalledTimes(0); + expect(startDeployMock).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); }); @@ -83,7 +93,7 @@ const render = async (props: Partial = {}) => { setSelectedImageTag: jest.fn(), selectedImageTag: '', startDeploy: startDeployMock, - ...props + ...props, }; return rtlRender(); diff --git a/frontend/app-development/features/dataModelling/DataModelling.test.tsx b/frontend/app-development/features/dataModelling/DataModelling.test.tsx index 2086fa96c92..016362fdaca 100644 --- a/frontend/app-development/features/dataModelling/DataModelling.test.tsx +++ b/frontend/app-development/features/dataModelling/DataModelling.test.tsx @@ -35,22 +35,12 @@ const org = 'org'; const app = 'app'; const user = userEvent.setup(); -// Mocks: -const getDatamodel = jest.fn().mockImplementation(() => Promise.resolve({})); -const getDatamodelsJson = jest.fn().mockImplementation(() => Promise.resolve([])); -const getDatamodelsXsd = jest.fn().mockImplementation(() => Promise.resolve([])); -const generateModels = jest.fn().mockImplementation(() => Promise.resolve()); - const render = ( queries: Partial = {}, queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { ...queriesMock, - getDatamodel, - getDatamodelsJson, - getDatamodelsXsd, - generateModels, ...queries, }; @@ -66,8 +56,8 @@ describe('DataModelling', () => { it('fetches models on mount', () => { render(); - expect(getDatamodelsJson).toHaveBeenCalledTimes(1); - expect(getDatamodelsXsd).toHaveBeenCalledTimes(1); + expect(queriesMock.getDatamodelsJson).toHaveBeenCalledTimes(1); + expect(queriesMock.getDatamodelsXsd).toHaveBeenCalledTimes(1); }); it('shows start dialog when no models are present and intro page is closed', () => { @@ -90,8 +80,10 @@ describe('DataModelling', () => { }); it('does not show start dialog when there are models present', async () => { - getDatamodelsJson.mockImplementation(() => Promise.resolve([jsonMetadata1Mock])); - render(); + const getDatamodelsJson = jest + .fn() + .mockImplementation(() => Promise.resolve([jsonMetadata1Mock])); + render({ getDatamodelsJson }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); expect( screen.queryByRole('heading', { name: textMock('app_data_modelling.landing_dialog_header') }), @@ -100,14 +92,19 @@ describe('DataModelling', () => { it('shows schema errors panel first when "generate model" button is clicked and returns errors', async () => { const queryClient = createQueryClientMock(); - generateModels.mockImplementation(() => - Promise.reject( - createApiErrorMock(400, 'DM_01', ['custom error message', 'another custom error message']), - ), - ); + const generateModels = jest + .fn() + .mockImplementation(() => + Promise.reject( + createApiErrorMock(400, 'DM_01', [ + 'custom error message', + 'another custom error message', + ]), + ), + ); queryClient.setQueryData([QueryKey.DatamodelsJson, org, app], [jsonMetadata1Mock]); queryClient.setQueryData([QueryKey.DatamodelsXsd, org, app], []); - render({}, queryClient); + render({ generateModels }, queryClient); const errorsPanel = screen.queryByText(textMock('api_errors.DM_01')); expect(errorsPanel).not.toBeInTheDocument(); @@ -121,14 +118,19 @@ describe('DataModelling', () => { it('closes schemaErrorsPanel when "close" button is clicked', async () => { const queryClient = createQueryClientMock(); - generateModels.mockImplementation(() => - Promise.reject( - createApiErrorMock(400, 'DM_01', ['custom error message', 'another custom error message']), - ), - ); + const generateModels = jest + .fn() + .mockImplementation(() => + Promise.reject( + createApiErrorMock(400, 'DM_01', [ + 'custom error message', + 'another custom error message', + ]), + ), + ); queryClient.setQueryData([QueryKey.DatamodelsJson, org, app], [jsonMetadata1Mock]); queryClient.setQueryData([QueryKey.DatamodelsXsd, org, app], []); - render({}, queryClient); + render({ generateModels }, queryClient); const generateModelButton = screen.getByRole('button', { name: textMock('schema_editor.generate_model_files'), diff --git a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/LandingPagePanel.test.tsx b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/LandingPagePanel.test.tsx index 5dec418a4b6..7545e2dcac0 100644 --- a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/LandingPagePanel.test.tsx +++ b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/LandingPagePanel.test.tsx @@ -17,20 +17,30 @@ describe('LandingPagePanel', () => { it('renders component', async () => { render(); - expect(screen.getByRole('heading', { name: textMock('app_data_modelling.landing_dialog_header') })).toBeInTheDocument(); - expect(screen.getByText(textMock('app_data_modelling.landing_dialog_paragraph'))).toBeInTheDocument(); + expect( + screen.getByRole('heading', { name: textMock('app_data_modelling.landing_dialog_header') }), + ).toBeInTheDocument(); + expect( + screen.getByText(textMock('app_data_modelling.landing_dialog_paragraph')), + ).toBeInTheDocument(); expect(screen.getByTestId(testids.fileSelectorInput)).toBeInTheDocument(); - expect(screen.getByRole('button', { name: textMock('app_data_modelling.landing_dialog_upload') })).toBeInTheDocument(); - expect(screen.getByRole('button', { name: textMock('app_data_modelling.landing_dialog_create') })).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: textMock('app_data_modelling.landing_dialog_upload') }), + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: textMock('app_data_modelling.landing_dialog_create') }), + ).toBeInTheDocument(); }); it('opens create dialog when clicking create button', async () => { render(); - const button = screen.getByRole('button', { name: textMock('app_data_modelling.landing_dialog_create') }); + const button = screen.getByRole('button', { + name: textMock('app_data_modelling.landing_dialog_create'), + }); await act(() => user.click(button)); - expect(landingPagePropsMock.openCreateNew).toBeCalledTimes(1); + expect(landingPagePropsMock.openCreateNew).toHaveBeenCalledTimes(1); }); }); diff --git a/frontend/app-development/features/textEditor/TextEditor.test.tsx b/frontend/app-development/features/textEditor/TextEditor.test.tsx index 536ab071ede..bd49951932c 100644 --- a/frontend/app-development/features/textEditor/TextEditor.test.tsx +++ b/frontend/app-development/features/textEditor/TextEditor.test.tsx @@ -15,19 +15,17 @@ const testTextResourceKey = 'test-key'; const testTextResourceValue = 'test-value'; const languages = ['nb', 'en']; -const queriesMock: Partial = { - getTextResources: jest.fn().mockImplementation(() => - Promise.resolve({ - resources: [ - { - id: testTextResourceKey, - value: testTextResourceValue, - }, - ], - }), - ), - getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(languages)), -}; +const getTextResources = jest.fn().mockImplementation(() => + Promise.resolve({ + resources: [ + { + id: testTextResourceKey, + value: testTextResourceValue, + }, + ], + }), +); +const getTextLanguages = jest.fn().mockImplementation(() => Promise.resolve(languages)); const mockSetSearchParams = jest.fn(); jest.mock('react-router-dom', () => ({ @@ -67,7 +65,7 @@ describe('TextEditor', () => { const addButton = screen.getByRole('button', { name: textMock('text_editor.new_text') }); await act(() => user.click(addButton)); - expect(upsertTextResources).toBeCalledTimes(2); + expect(upsertTextResources).toHaveBeenCalledTimes(2); }); it('updates text resource when editing text', async () => { @@ -82,7 +80,9 @@ describe('TextEditor', () => { await act(() => user.type(textarea, 'test')); await act(() => user.tab()); - expect(upsertTextResources).toBeCalledWith(org, app, 'nb', { [testTextResourceKey]: 'test' }); + expect(upsertTextResources).toHaveBeenCalledWith(org, app, 'nb', { + [testTextResourceKey]: 'test', + }); }); it('updates text id when editing text id', async () => { @@ -100,7 +100,9 @@ describe('TextEditor', () => { await act(() => user.type(textarea, 'test')); await act(() => user.tab()); - expect(updateTextId).toBeCalledWith(org, app, [{ newId: 'test', oldId: testTextResourceKey }]); + expect(updateTextId).toHaveBeenCalledWith(org, app, [ + { newId: 'test', oldId: testTextResourceKey }, + ]); }); it('deletes text id when clicking delete button', async () => { @@ -118,7 +120,7 @@ describe('TextEditor', () => { }); await act(() => user.click(confirmButton)); - expect(updateTextId).toBeCalledWith(org, app, [{ oldId: testTextResourceKey }]); + expect(updateTextId).toHaveBeenCalledWith(org, app, [{ oldId: testTextResourceKey }]); }); it('adds new language when clicking add button', async () => { @@ -140,7 +142,7 @@ describe('TextEditor', () => { expect(addBtn).not.toBeDisabled(); await act(() => user.click(addBtn)); - expect(addLanguageCode).toBeCalledWith(org, app, 'se', { + expect(addLanguageCode).toHaveBeenCalledWith(org, app, 'se', { language: 'se', resources: [{ id: testTextResourceKey, value: '' }], }); @@ -161,7 +163,7 @@ describe('TextEditor', () => { }); await act(() => user.click(confirmButton)); - expect(deleteLanguageCode).toBeCalledWith(org, app, 'en'); + expect(deleteLanguageCode).toHaveBeenCalledWith(org, app, 'en'); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -177,7 +179,8 @@ describe('TextEditor', () => { const render = async (queries: Partial = {}) => { const view = renderWithProviders(, { queries: { - ...queriesMock, + ...getTextResources, + ...getTextLanguages, ...queries, }, startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, diff --git a/frontend/packages/schema-editor/src/components/TreeView/SchemaItem.test.tsx b/frontend/packages/schema-editor/src/components/TreeView/SchemaItem.test.tsx index bee1228cf06..01ef8405682 100644 --- a/frontend/packages/schema-editor/src/components/TreeView/SchemaItem.test.tsx +++ b/frontend/packages/schema-editor/src/components/TreeView/SchemaItem.test.tsx @@ -54,7 +54,7 @@ describe('SchemaItem', () => { await act(() => user.click(confirmButton)); await waitFor(() => { - expect(dispatchSpy).toBeCalledWith({ + expect(dispatchSpy).toHaveBeenCalledWith({ payload: '#/$defs/Test', type: 'schemaEditor/removeSelection', }); @@ -73,7 +73,7 @@ describe('SchemaItem', () => { await act(() => user.click(cancelButton)); await waitFor(() => { - expect(dispatchSpy).toBeCalledTimes(0); + expect(dispatchSpy).toHaveBeenCalledTimes(0); }); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -87,7 +87,7 @@ describe('SchemaItem', () => { await act(() => user.click(document.body)); await waitFor(() => { - expect(dispatchSpy).toBeCalledTimes(0); + expect(dispatchSpy).toHaveBeenCalledTimes(0); }); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -134,6 +134,6 @@ const render = async (props: Partial = {}) => { })( - + , ); }; diff --git a/frontend/packages/schema-model/src/lib/mutations/ui-schema-reducers.test.ts b/frontend/packages/schema-model/src/lib/mutations/ui-schema-reducers.test.ts index 0aa1831eb34..5f85dd97bad 100644 --- a/frontend/packages/schema-model/src/lib/mutations/ui-schema-reducers.test.ts +++ b/frontend/packages/schema-model/src/lib/mutations/ui-schema-reducers.test.ts @@ -238,7 +238,7 @@ describe('ui-schema-reducers', () => { it('Calls the callback function with the new pointer', () => { result = setPropertyName(createNewModelMock(), args); - expect(callback).toBeCalledTimes(1); + expect(callback).toHaveBeenCalledTimes(1); expect(callback).toHaveBeenCalledWith(expectedPointer); }); }); diff --git a/frontend/packages/shared/src/components/AltinnConfirmDialog.test.tsx b/frontend/packages/shared/src/components/AltinnConfirmDialog.test.tsx index e9d84d863b0..66866ed7725 100644 --- a/frontend/packages/shared/src/components/AltinnConfirmDialog.test.tsx +++ b/frontend/packages/shared/src/components/AltinnConfirmDialog.test.tsx @@ -44,8 +44,8 @@ describe('AltinnConfirmDialog', () => { const confirmButton = screen.getByRole('button', { name: confirmTextMock }); await act(() => user.click(confirmButton)); - expect(onConfirmMock).toBeCalledTimes(1); - expect(onCloseMock).toBeCalledTimes(1); + expect(onConfirmMock).toHaveBeenCalledTimes(1); + expect(onCloseMock).toHaveBeenCalledTimes(1); }); it('should call onClose when clicking the cancel button', async () => { @@ -79,6 +79,6 @@ const render = async (props: Partial = {}) => { return rtlRender(

{descriptionTextMock}

-
+ , ); }; diff --git a/frontend/packages/shared/src/components/InputActionWrapper/InputActionWrapper.test.tsx b/frontend/packages/shared/src/components/InputActionWrapper/InputActionWrapper.test.tsx index 4c2b307f7e4..e5cb6b1a0a3 100644 --- a/frontend/packages/shared/src/components/InputActionWrapper/InputActionWrapper.test.tsx +++ b/frontend/packages/shared/src/components/InputActionWrapper/InputActionWrapper.test.tsx @@ -59,21 +59,21 @@ describe('InputActionWrapper', () => { render(); const saveButton = screen.getByLabelText('general.save'); await act(() => user.click(saveButton)); - expect(mockProps.onSaveClick).toBeCalledTimes(1); + expect(mockProps.onSaveClick).toHaveBeenCalledTimes(1); }); it('triggers delete click on delete button click', async () => { render(); const deleteButton = screen.getByLabelText('general.delete'); await act(() => user.click(deleteButton)); - expect(mockProps.onDeleteClick).toBeCalledTimes(1); + expect(mockProps.onDeleteClick).toHaveBeenCalledTimes(1); }); it('check that handleActionClick is called when edit button is clicked', async () => { render(); const editButton = screen.getByLabelText('general.edit'); await act(() => user.click(editButton)); - expect(mockProps.onEditClick).toBeCalledTimes(1); + expect(mockProps.onEditClick).toHaveBeenCalledTimes(1); }); it('check that handleHover is called when onMouseOver is called ', async () => { diff --git a/frontend/packages/text-editor/src/RightMenu.test.tsx b/frontend/packages/text-editor/src/RightMenu.test.tsx index a255e5bdb32..c8e02b666ce 100644 --- a/frontend/packages/text-editor/src/RightMenu.test.tsx +++ b/frontend/packages/text-editor/src/RightMenu.test.tsx @@ -28,8 +28,10 @@ describe('RightMenu', () => { const render = async () => { rtlRender(); - await waitFor(() => { expect(screen.getByRole('combobox')).toBeInTheDocument(); }); - } + await waitFor(() => { + expect(screen.getByRole('combobox')).toBeInTheDocument(); + }); + }; describe('Delete confirmation dialog', () => { it('should open the confirmation dialog when clicking the delete button', async () => { @@ -41,10 +43,14 @@ describe('RightMenu', () => { const dialog = screen.getByRole('dialog'); expect(dialog).toBeInTheDocument(); - const text = await screen.findByText(textMock('schema_editor.language_display_confirm_delete')); + const text = await screen.findByText( + textMock('schema_editor.language_display_confirm_delete'), + ); expect(text).toBeInTheDocument(); - const confirmButton = screen.getByRole('button', { name: textMock('schema_editor.language_confirm_deletion') }); + const confirmButton = screen.getByRole('button', { + name: textMock('schema_editor.language_confirm_deletion'), + }); expect(confirmButton).toBeInTheDocument(); const cancelButton = screen.getByRole('button', { name: textMock('general.cancel') }); @@ -57,10 +63,12 @@ describe('RightMenu', () => { const deleteButton = screen.getByTestId(testids.deleteButton('en')); await act(() => user.click(deleteButton)); - const confirmButton = screen.getByRole('button', { name: textMock('schema_editor.language_confirm_deletion') }); + const confirmButton = screen.getByRole('button', { + name: textMock('schema_editor.language_confirm_deletion'), + }); await act(() => user.click(confirmButton)); - expect(defaultProps.deleteLanguage).toBeCalledWith('en'); + expect(defaultProps.deleteLanguage).toHaveBeenCalledWith('en'); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -73,7 +81,7 @@ describe('RightMenu', () => { const cancelButton = screen.getByRole('button', { name: textMock('general.cancel') }); await act(() => user.click(cancelButton)); - expect(defaultProps.deleteLanguage).toBeCalledTimes(0); + expect(defaultProps.deleteLanguage).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -85,7 +93,7 @@ describe('RightMenu', () => { await act(() => user.click(document.body)); - expect(defaultProps.deleteLanguage).toBeCalledTimes(0); + expect(defaultProps.deleteLanguage).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); }); diff --git a/frontend/packages/text-editor/src/TextRow.test.tsx b/frontend/packages/text-editor/src/TextRow.test.tsx index 71d78af3098..ed4cf5fa259 100644 --- a/frontend/packages/text-editor/src/TextRow.test.tsx +++ b/frontend/packages/text-editor/src/TextRow.test.tsx @@ -33,7 +33,7 @@ describe('TextRow', () => { - + , ); }; @@ -147,7 +147,7 @@ describe('TextRow', () => { }); await act(() => user.click(confirmButton)); - expect(removeEntry).toBeCalledWith({ textId: 'key1' }); + expect(removeEntry).toHaveBeenCalledWith({ textId: 'key1' }); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -162,7 +162,7 @@ describe('TextRow', () => { const cancelButton = screen.getByRole('button', { name: textMock('general.cancel') }); await act(() => user.click(cancelButton)); - expect(removeEntry).toBeCalledTimes(0); + expect(removeEntry).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -176,7 +176,7 @@ describe('TextRow', () => { await act(() => user.click(document.body)); - expect(removeEntry).toBeCalledTimes(0); + expect(removeEntry).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); }); diff --git a/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx b/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx index 9dd631d3d39..7128a8dd9a3 100644 --- a/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx +++ b/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx @@ -52,8 +52,8 @@ describe('FormComponent', () => { const component = screen.getByRole('listitem'); await act(() => user.click(component)); - expect(handleSaveMock).toBeCalledTimes(1); - expect(handleEditMock).toBeCalledTimes(1); + expect(handleSaveMock).toHaveBeenCalledTimes(1); + expect(handleEditMock).toHaveBeenCalledTimes(1); }); describe('Delete confirmation dialog', () => { @@ -91,7 +91,7 @@ describe('FormComponent', () => { }); await act(() => user.click(confirmButton)); - expect(mockDeleteFormComponent).toBeCalledWith(component1IdMock); + expect(mockDeleteFormComponent).toHaveBeenCalledWith(component1IdMock); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -104,7 +104,7 @@ describe('FormComponent', () => { const cancelButton = screen.getByRole('button', { name: textMock('general.cancel') }); await act(() => user.click(cancelButton)); - expect(mockDeleteFormComponent).toBeCalledTimes(0); + expect(mockDeleteFormComponent).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -119,7 +119,7 @@ describe('FormComponent', () => { }); await act(() => user.click(confirmButton)); - expect(mockDeleteFormComponent).toBeCalledTimes(1); + expect(mockDeleteFormComponent).toHaveBeenCalledTimes(1); expect(handleDiscardMock).toHaveBeenCalledTimes(1); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); @@ -132,7 +132,7 @@ describe('FormComponent', () => { await act(() => user.click(document.body)); - expect(mockDeleteFormComponent).toBeCalledTimes(0); + expect(mockDeleteFormComponent).toHaveBeenCalledTimes(0); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); }); diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index 1c98bf21e1a..629723ff5b8 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -206,7 +206,7 @@ describe('TextResource', () => { }), ), ); - expect(handleRemoveTextResource).toBeCalledTimes(1); + expect(handleRemoveTextResource).toHaveBeenCalledTimes(1); }); it('Does not call handleRemoveTextResourceBinding is called when cancel delete button is clicked', async () => { diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx index 80fcf3df40c..af1a016b002 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx @@ -8,53 +8,48 @@ import { textMock } from '../../../../../../testing/mocks/i18nMock'; import { ComponentType } from 'app-shared/types/ComponentType'; import userEvent from '@testing-library/user-event'; -const getDatamodelMetadata = () => - Promise.resolve({ - elements: { - testModel: { - id: 'testModel', - type: 'ComplexType', - dataBindingName: 'testModel', - displayString: 'testModel', - isReadOnly: false, - isTagContent: false, - jsonSchemaPointer: '#/definitions/testModel', - maxOccurs: 1, - minOccurs: 1, - name: 'testModel', - parentElement: null, - restrictions: [], - texts: [], - xmlSchemaXPath: '/testModel', - xPath: '/testModel', - }, - 'testModel.field1': { - id: 'testModel.field1', - type: 'SimpleType', - dataBindingName: 'testModel.field1', - displayString: 'testModel.field1', - isReadOnly: false, - isTagContent: false, - jsonSchemaPointer: '#/definitions/testModel/properteis/field1', - maxOccurs: 1, - minOccurs: 1, - name: 'testModel/field1', - parentElement: null, - restrictions: [], - texts: [], - xmlSchemaXPath: '/testModel/field1', - xPath: '/testModel/field1', - }, +const datamodelMetadata = { + elements: { + testModel: { + id: 'testModel', + type: 'ComplexType', + dataBindingName: 'testModel', + displayString: 'testModel', + isReadOnly: false, + isTagContent: false, + jsonSchemaPointer: '#/definitions/testModel', + maxOccurs: 1, + minOccurs: 1, + name: 'testModel', + parentElement: null, + restrictions: [], + texts: [], + xmlSchemaXPath: '/testModel', + xPath: '/testModel', }, - }); + 'testModel.field1': { + id: 'testModel.field1', + type: 'SimpleType', + dataBindingName: 'testModel.field1', + displayString: 'testModel.field1', + isReadOnly: false, + isTagContent: false, + jsonSchemaPointer: '#/definitions/testModel/properteis/field1', + maxOccurs: 1, + minOccurs: 1, + name: 'testModel/field1', + parentElement: null, + restrictions: [], + texts: [], + xmlSchemaXPath: '/testModel/field1', + xPath: '/testModel/field1', + }, + }, +}; -const render = async ({ - dataModelBindings = {}, - handleComponentChange = jest.fn(), - handleDataModelChange = jest.fn(), - setSelectedOption = jest.fn(), - onEditClick = jest.fn(), -} = {}) => { +const getDatamodelMetadata = () => Promise.resolve(datamodelMetadata); + +const render = async ({ dataModelBindings = {}, handleComponentChange = jest.fn() } = {}) => { const appData: IAppDataState = { ...appDataMock, textResources: { @@ -65,8 +60,6 @@ const render = async ({ return renderWithMockStore( { appData }, { getDatamodelMetadata }, - handleDataModelChange(), - setSelectedOption(), )( { }); it('check that handleDataModelChange is called', async () => { - const handleDataModelChange = jest.fn(); - const dataModelSelectVisible = jest.fn(); - await render({ handleDataModelChange }); + const handleComponentChange = jest.fn(); + await render({ handleComponentChange }); const linkIcon = screen.getByText(/ux_editor.modal_properties_data_model_link/i); await waitFor(async () => { await userEvent.click(linkIcon); }); - dataModelSelectVisible(true); const select = screen.getByRole('combobox'); - const option = within(select).getByText(''); + await waitFor(async () => await userEvent.click(select)); await waitFor(async () => { - await userEvent.click(option); + await userEvent.click( + screen.getByRole('option', { + name: datamodelMetadata.elements.testModel.dataBindingName, + }), + ); + }); + expect(handleComponentChange).toHaveBeenCalledWith({ + dataModelBindings: { simpleBinding: 'testModel' }, + id: 'someComponentId', + itemType: 'COMPONENT', + required: true, + textResourceBindings: { title: 'ServiceName' }, + timeStamp: undefined, + type: 'Input', }); - expect(handleDataModelChange).toHaveBeenCalled(); }); it('should render save icon', async () => { @@ -194,84 +197,65 @@ describe('EditDataModelBindings', () => { expect(screen.getByText(/ux_editor.modal_properties_data_model_link/i)).toBeInTheDocument(); }); - it('should call handleDataModelChange and update setSelectedOption on delete button click', async () => { - const handleDataModelChange = jest.fn(); - const setSelectedOption = String(''); + it('deletes existing data model link', async () => { + const handleComponentChange = jest.fn(); + const dataModelBindingKey = 'testModel.field1'; - await render({ handleDataModelChange }); + await render({ + handleComponentChange, + dataModelBindings: { simpleBinding: dataModelBindingKey }, + }); + + const datamodelText = screen.getByText(dataModelBindingKey); + expect(datamodelText).toBeInTheDocument(); - const linkIcon = screen.getByText(/ux_editor.modal_properties_data_model_link/i); await waitFor(async () => { - await userEvent.click(linkIcon); + await userEvent.hover(datamodelText); }); - expect(await screen.findByText('testModel.field1')).toBeInTheDocument(); + const editIcon = screen.getByRole('button', { name: textMock('general.edit') }); + await waitFor(async () => { + await userEvent.click(editIcon); + }); + + expect(await screen.findByText(dataModelBindingKey)).toBeInTheDocument(); const deleteButton = await screen.findByRole('button', { name: /general.delete/i }); await waitFor(async () => { await userEvent.click(deleteButton); }); - expect(handleDataModelChange).toBeCalled; - expect(typeof setSelectedOption).toEqual('string'); + expect(handleComponentChange).toHaveBeenCalledWith({ + dataModelBindings: { simpleBinding: '' }, + id: 'someComponentId', + itemType: 'COMPONENT', + required: false, + textResourceBindings: { title: 'ServiceName' }, + timeStamp: undefined, + type: 'Input', + }); }); - it('should call handleDataModelChange and setSelectedOption on data model change', async () => { - const handleDataModelChange = jest.fn(); - const setSelectedOption = jest.fn(); + it('shows edit form', async () => { + const dataModelBindingKey = 'testModel.field1'; + await render({ + dataModelBindings: { simpleBinding: dataModelBindingKey }, + }); - await render({ handleDataModelChange, setSelectedOption }); + const datamodelText = screen.getByText(dataModelBindingKey); + expect(datamodelText).toBeInTheDocument(); - const linkIcon = screen.getByText(/ux_editor.modal_properties_data_model_link/i); await waitFor(async () => { - await userEvent.click(linkIcon); + await userEvent.hover(datamodelText); }); - expect( - await screen.findByText(textMock('ux_editor.modal_properties_data_model_helper')), - ).toBeInTheDocument(); - expect(await screen.findByText('testModel.field1')).toBeInTheDocument(); - - expect(handleDataModelChange).toBeCalled; - expect(setSelectedOption).toBeCalled; - }); - - it('should render LinkedDataModelContainer component when an option is selected', async () => { - const handleDataModelChange = jest.fn(); - const setSelectedOption = jest.fn(); - - await render({ handleDataModelChange, setSelectedOption }); - - const linkIcon = screen.getByText(/ux_editor.modal_properties_data_model_link/i); + const editIcon = screen.getByRole('button', { name: textMock('general.edit') }); await waitFor(async () => { - await userEvent.click(linkIcon); + await userEvent.click(editIcon); }); expect( - await screen.findByText(textMock('ux_editor.modal_properties_data_model_helper')), + screen.getByText(textMock('ux_editor.modal_properties_data_model_helper')), ).toBeInTheDocument(); - expect(await screen.findByText('testModel.field1')).toBeInTheDocument(); - - expect(handleDataModelChange).toBeCalled; - expect(setSelectedOption).toBeCalled; - - const linkedDataModelContainer = await screen.findByText('testModel.field1'); - expect(linkedDataModelContainer).toBeInTheDocument(); - }); - - it('check that onEditClick is called', async () => { - const onEditClick = jest.fn(); - await render({ onEditClick }); - - const linkIcon = screen.getByText(/ux_editor.modal_properties_data_model_link/i); - await waitFor(async () => { - await userEvent.click(linkIcon); - }); - const editIcon = screen.getByRole('button', { name: /Edit/i }); - await waitFor(async () => { - await userEvent.hover(editIcon); - }); - - expect(editIcon).toBeInTheDocument(); - expect(onEditClick).toHaveBeenCalled; + expect(screen.getByRole('combobox').getAttribute('value')).toEqual(dataModelBindingKey); }); it('show right data model when switching component', async () => { diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx index 696463fc5e0..3db4fedbc59 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx @@ -31,8 +31,8 @@ describe('EditTextResourceBindings component', () => { const textResources: ITextResource[] = [ { id: 'test-text', - value: 'This is a test' - } + value: 'This is a test', + }, ]; test('that it renders', async () => { @@ -45,14 +45,20 @@ describe('EditTextResourceBindings component', () => { test('that handleComponentChange is called when adding a new text', async () => { const handleComponentChange = jest.fn(); - await renderEditTextResourceBindingsComponent({ handleComponentChange, textKey: 'does-not-exist' }); + await renderEditTextResourceBindingsComponent({ + handleComponentChange, + textKey: 'does-not-exist', + }); await act(() => user.click(screen.getByLabelText(textMock('general.add')))); - expect(handleComponentChange).toBeCalledTimes(1); + expect(handleComponentChange).toHaveBeenCalledTimes(1); }); test('that handleComponentChange is called when choosing existing text', async () => { const handleComponentChange = jest.fn(); - await renderEditTextResourceBindingsComponent({ handleComponentChange, textKey: 'does-not-exist' }); + await renderEditTextResourceBindingsComponent({ + handleComponentChange, + textKey: 'does-not-exist', + }); // Click search button await act(() => user.click(screen.getByLabelText(textMock('general.search')))); @@ -65,39 +71,53 @@ describe('EditTextResourceBindings component', () => { // Select text from available options await act(() => user.click(screen.getByRole('option', { name: textResources[0].id }))); - expect(handleComponentChange).toBeCalledTimes(1); - expect(handleComponentChange).toBeCalledWith({ + expect(handleComponentChange).toHaveBeenCalledTimes(1); + expect(handleComponentChange).toHaveBeenCalledWith({ ...mockComponent, textResourceBindings: { ...mockComponent.textResourceBindings, - 'does-not-exist': 'test-text' - } + 'does-not-exist': 'test-text', + }, }); }); test('That handleComponentChange and removeTextResourceBinding are called when confirm delete textResourceBinding button is clicked', async () => { const handleComponentChange = jest.fn(); const removeTextResourceBinding = jest.fn(); - await renderEditTextResourceBindingsComponent({ handleComponentChange, removeTextResourceBinding }); + await renderEditTextResourceBindingsComponent({ + handleComponentChange, + removeTextResourceBinding, + }); await act(() => user.click(screen.getByRole('button', { name: textMock('general.delete') }))); - await act(() => user.click(screen.getByRole('button', { name: textMock('ux_editor.text_resource_bindings.delete_confirm') }))); - expect(handleComponentChange).toBeCalledTimes(1); - expect(handleComponentChange).toBeCalledWith({ + await act(() => + user.click( + screen.getByRole('button', { + name: textMock('ux_editor.text_resource_bindings.delete_confirm'), + }), + ), + ); + expect(handleComponentChange).toHaveBeenCalledTimes(1); + expect(handleComponentChange).toHaveBeenCalledWith({ ...mockComponent, textResourceBindings: {}, }); - expect(removeTextResourceBinding).toBeCalledTimes(1); + expect(removeTextResourceBinding).toHaveBeenCalledTimes(1); }); const waitForData = async () => { - const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()).renderHookResult.result; - const { result } = renderHookWithMockStore({}, { - getTextLanguages: () => Promise.resolve(['nb', 'nn', 'en']), - getTextResources: (_o, _a, lang) => Promise.resolve({ - language: lang, - resources: textResources - }), - })(() => useTextResourcesQuery(org, app)).renderHookResult; + const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) + .renderHookResult.result; + const { result } = renderHookWithMockStore( + {}, + { + getTextLanguages: () => Promise.resolve(['nb', 'nn', 'en']), + getTextResources: (_o, _a, lang) => + Promise.resolve({ + language: lang, + resources: textResources, + }), + }, + )(() => useTextResourcesQuery(org, app)).renderHookResult; await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true)); await waitFor(() => expect(result.current.isSuccess).toBe(true)); }; @@ -111,12 +131,14 @@ describe('EditTextResourceBindings component', () => { }: Partial) => { await waitForData(); - return renderWithMockStore()(); + return renderWithMockStore()( + , + ); }; }); From 9615bba12ac7d39bd3e3a34d2fd79173396d0a8b Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 19 Dec 2023 19:24:29 +0100 Subject: [PATCH 05/15] Fix tests --- .../features/textEditor/TextEditor.test.tsx | 4 +-- .../packages/shared/src/mocks/queriesMock.ts | 2 +- frontend/packages/ux-editor/src/App.test.tsx | 9 ++++++- .../FormComponent/FormComponent.test.tsx | 11 ++++++-- .../src/components/TextResource.test.tsx | 10 ++++++- .../config/EditFormContainer.test.tsx | 26 +++++++++++++------ .../Panel/PanelComponent.test.tsx | 16 +++++++++--- .../config/editModal/EditCodeList.test.tsx | 23 +++++++++++----- .../NavigationMenu/NavigationMenu.test.tsx | 17 +++++++++--- .../PageAccordion/PageAccordion.test.tsx | 17 +++++++++--- .../ReceiptContent/ReceiptContent.test.tsx | 18 +++++++++---- .../src/containers/FormDesigner.test.tsx | 24 ++++++++++++----- .../mutations/useAddLayoutMutation.test.ts | 19 +++++++++----- .../useDeleteFormContainerMutation.test.ts | 10 ++++--- ...seUpdateFormComponentOrderMutation.test.ts | 9 ++++--- .../useUpdateFormContainerMutation.test.ts | 24 ++++++++++++----- .../useUpdateLayoutNameMutation.test.ts | 12 ++++++--- .../useUpdateLayoutOrderMutation.test.ts | 12 ++++++--- .../src/hooks/useFormLayoutsSelector.test.ts | 8 +++--- .../src/hooks/useValidateComponent.test.ts | 14 ++++++++-- 20 files changed, 207 insertions(+), 78 deletions(-) diff --git a/frontend/app-development/features/textEditor/TextEditor.test.tsx b/frontend/app-development/features/textEditor/TextEditor.test.tsx index bd49951932c..6c9e4d27892 100644 --- a/frontend/app-development/features/textEditor/TextEditor.test.tsx +++ b/frontend/app-development/features/textEditor/TextEditor.test.tsx @@ -179,8 +179,8 @@ describe('TextEditor', () => { const render = async (queries: Partial = {}) => { const view = renderWithProviders(, { queries: { - ...getTextResources, - ...getTextLanguages, + getTextResources, + getTextLanguages, ...queries, }, startUrl: `${APP_DEVELOPMENT_BASENAME}/${org}/${app}`, diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts index 5a918585022..d10580e47e8 100644 --- a/frontend/packages/shared/src/mocks/queriesMock.ts +++ b/frontend/packages/shared/src/mocks/queriesMock.ts @@ -23,7 +23,7 @@ export const queriesMock: ServicesContextProps = { getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve([])), getComponentsCommonDefsSchema: jest.fn().mockImplementation(() => Promise.resolve([])), getDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), - getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({ elements: {} })), getDatamodelsJson: jest.fn().mockImplementation(() => Promise.resolve([])), getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve([])), getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve([])), diff --git a/frontend/packages/ux-editor/src/App.test.tsx b/frontend/packages/ux-editor/src/App.test.tsx index b48964bf1e0..c8db7804b36 100644 --- a/frontend/packages/ux-editor/src/App.test.tsx +++ b/frontend/packages/ux-editor/src/App.test.tsx @@ -1,18 +1,25 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; -import { renderWithMockStore } from './testing/mocks'; +import { formLayoutSettingsMock, renderWithMockStore } from './testing/mocks'; import { App } from './App'; import { textMock } from '../../../testing/mocks/i18nMock'; import { typedLocalStorage } from 'app-shared/utils/webStorage'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { appStateMock } from './testing/stateMocks'; import { AppContextProps } from './AppContext'; +import ruleHandlerMock from './testing/ruleHandlerMock'; +import { layoutSetsMock } from './testing/layoutMock'; const { selectedLayoutSet } = appStateMock.formDesigner.layout; const removeSelectedLayoutSetMock = jest.fn(); const render = (selectedLayoutSetForRender: string) => { const queries: Partial = { getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('test')), + getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), + getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve(layoutSetsMock)), + getFormLayoutSettings: jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), }; const appContextProps: Partial = { selectedLayoutSet: selectedLayoutSetForRender, diff --git a/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx b/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx index 7128a8dd9a3..2d6154fedd7 100644 --- a/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx +++ b/frontend/packages/ux-editor/src/components/FormComponent/FormComponent.test.tsx @@ -5,7 +5,11 @@ import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; import type { IFormComponentProps } from './FormComponent'; import { FormComponent } from './FormComponent'; -import { renderHookWithMockStore, renderWithMockStore } from '../../testing/mocks'; +import { + renderHookWithMockStore, + renderWithMockStore, + textLanguagesMock, +} from '../../testing/mocks'; import { component1IdMock, component1Mock } from '../../testing/layoutMock'; import { textMock } from '../../../../../testing/mocks/i18nMock'; import { useTextResourcesQuery } from 'app-shared/hooks/queries/useTextResourcesQuery'; @@ -200,7 +204,10 @@ const waitForData = async () => { const { result: texts } = renderHookWithMockStore( {}, { - getTextResources: () => Promise.resolve({ language: 'nb', resources: nbTextResources }), + getTextResources: jest + .fn() + .mockImplementation(() => Promise.resolve({ language: 'nb', resources: nbTextResources })), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), }, )(() => useTextResourcesQuery(org, app)).renderHookResult; await waitFor(() => expect(texts.current.isSuccess).toBe(true)); diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index 629723ff5b8..c7e7bafb327 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -2,7 +2,12 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import type { ITextResource, ITextResourcesWithLanguage } from 'app-shared/types/global'; import { TextResource, TextResourceProps } from './TextResource'; -import { queryClientMock, renderHookWithMockStore, renderWithMockStore } from '../testing/mocks'; +import { + queryClientMock, + renderHookWithMockStore, + renderWithMockStore, + textLanguagesMock, +} from '../testing/mocks'; import { useLayoutSchemaQuery } from '../hooks/queries/useLayoutSchemaQuery'; import { act, screen, waitFor } from '@testing-library/react'; import { textMock } from '../../../../testing/mocks/i18nMock'; @@ -10,6 +15,7 @@ import { useTextResourcesQuery } from 'app-shared/hooks/queries/useTextResources import { DEFAULT_LANGUAGE } from 'app-shared/constants'; import { typedLocalStorage } from 'app-shared/utils/webStorage'; import { addFeatureFlagToLocalStorage } from 'app-shared/utils/featureToggleUtils'; +import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; const user = userEvent.setup(); @@ -245,6 +251,7 @@ const renderAndOpenSearchSection = async () => { }; const waitForData = async (resources: ITextResource[]) => { + const getTextLanguages = jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)); const { result } = renderHookWithMockStore( {}, { @@ -254,6 +261,7 @@ const waitForData = async (resources: ITextResource[]) => { resources, }), ), + getTextLanguages, }, )(() => useTextResourcesQuery(org, app)).renderHookResult; const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) diff --git a/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx b/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx index 745728443d2..e8a3e120b2a 100644 --- a/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx @@ -5,9 +5,13 @@ import type { IEditFormContainerProps } from './EditFormContainer'; import { EditFormContainer } from './EditFormContainer'; import { useFormLayoutsQuery } from '../../hooks/queries/useFormLayoutsQuery'; import { useFormLayoutSettingsQuery } from '../../hooks/queries/useFormLayoutSettingsQuery'; -import { renderHookWithMockStore, renderWithMockStore } from '../../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../../testing/mocks'; import { useLayoutSchemaQuery } from '../../hooks/queries/useLayoutSchemaQuery'; -import { container1IdMock, layoutMock } from '../../testing/layoutMock'; +import { container1IdMock, externalLayoutsMock, layoutMock } from '../../testing/layoutMock'; import { textMock } from '../../../../../testing/mocks/i18nMock'; const user = userEvent.setup(); @@ -80,12 +84,18 @@ describe('EditFormContainer', () => { }); const waitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) .renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); diff --git a/frontend/packages/ux-editor/src/components/config/componentSpecificContent/Panel/PanelComponent.test.tsx b/frontend/packages/ux-editor/src/components/config/componentSpecificContent/Panel/PanelComponent.test.tsx index 3db0bb6aaba..989b28f8cfd 100644 --- a/frontend/packages/ux-editor/src/components/config/componentSpecificContent/Panel/PanelComponent.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/componentSpecificContent/Panel/PanelComponent.test.tsx @@ -3,7 +3,11 @@ import { act, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { PanelComponent } from './PanelComponent'; import { FormComponent } from '../../../../types/FormComponent'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../../../../testing/mocks'; import { useLayoutSchemaQuery } from '../../../../hooks/queries/useLayoutSchemaQuery'; import { ComponentType } from 'app-shared/types/ComponentType'; import { useFormLayoutsQuery } from '../../../../hooks/queries/useFormLayoutsQuery'; @@ -30,12 +34,16 @@ const mockHandleComponentChange = jest.fn(); const user = userEvent.setup(); const waitForData = async () => { + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet), ).renderHookResult.result; - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) .renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx index e6e723f19ac..a2bde6e1128 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx @@ -2,18 +2,28 @@ import React from 'react'; import { EditCodeList } from './EditCodeList'; import { screen, waitFor } from '@testing-library/react'; import { ComponentType } from 'app-shared/types/ComponentType'; -import { renderWithMockStore, renderHookWithMockStore } from '../../../testing/mocks'; +import { + renderWithMockStore, + renderHookWithMockStore, + optionListIdsMock, +} from '../../../testing/mocks'; import { useLayoutSchemaQuery } from '../../../hooks/queries/useLayoutSchemaQuery'; describe('EditCodeList', () => { it('should render the component', async () => { - await render(); + await render({ + queries: { + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + }, + }); expect(await screen.findByText('Bytt til egendefinert kodeliste')).toBeInTheDocument(); }); it('should render the component when optionListIds is undefined', async () => { await render({ - queries: { getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(undefined)) }, + queries: { + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + }, }); expect(await screen.findByText('Bytt til egendefinert kodeliste')).toBeInTheDocument(); @@ -21,7 +31,8 @@ describe('EditCodeList', () => { }); const waitForData = async () => { - const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()).renderHookResult.result; + const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) + .renderHookResult.result; await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true)); }; @@ -30,7 +41,7 @@ const render = async ({ handleComponentChange = jest.fn(), queries = {} } = {}) renderWithMockStore( {}, - queries + queries, )( + />, ); }; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx index 25737013d17..6a5fc03ba75 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/NavigationMenu/NavigationMenu.test.tsx @@ -4,7 +4,11 @@ import { NavigationMenu, NavigationMenuProps } from './NavigationMenu'; import userEvent from '@testing-library/user-event'; import { textMock } from '../../../../../../../testing/mocks/i18nMock'; import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../../../../testing/mocks'; import { formDesignerMock } from '../../../../testing/stateMocks'; import { useFormLayoutSettingsQuery } from '../../../../hooks/queries/useFormLayoutSettingsQuery'; @@ -113,9 +117,14 @@ describe('NavigationMenu', () => { }); const waitForData = async () => { - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet), - ).renderHookResult.result; + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet)).renderHookResult + .result; await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/PageAccordion.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/PageAccordion.test.tsx index de5b64389b5..a678dcd603f 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/PageAccordion.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/PageAccordion/PageAccordion.test.tsx @@ -5,7 +5,11 @@ import userEvent from '@testing-library/user-event'; import { textMock } from '../../../../../../testing/mocks/i18nMock'; import { formDesignerMock } from '../../../testing/stateMocks'; import { useFormLayoutSettingsQuery } from '../../../hooks/queries/useFormLayoutSettingsQuery'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../../../testing/mocks'; import { layout2NameMock } from '../../../testing/layoutMock'; const mockOrg = 'org'; @@ -96,9 +100,14 @@ describe('PageAccordion', () => { }); const waitForData = async () => { - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet), - ).renderHookResult.result; + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet)).renderHookResult + .result; await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/containers/DesignView/ReceiptContent/ReceiptContent.test.tsx b/frontend/packages/ux-editor/src/containers/DesignView/ReceiptContent/ReceiptContent.test.tsx index 4f8c7ba2f07..f13060352de 100644 --- a/frontend/packages/ux-editor/src/containers/DesignView/ReceiptContent/ReceiptContent.test.tsx +++ b/frontend/packages/ux-editor/src/containers/DesignView/ReceiptContent/ReceiptContent.test.tsx @@ -11,7 +11,11 @@ import { layout2NameMock, } from '../../../testing/layoutMock'; import { IInternalLayout } from '../../../types/global'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../../../testing/mocks'; import { useFormLayoutSettingsQuery } from '../../../hooks/queries/useFormLayoutSettingsQuery'; import { useFormLayoutsQuery } from '../../../hooks/queries/useFormLayoutsQuery'; import { DragAndDrop } from 'app-shared/components/dragAndDrop'; @@ -107,13 +111,17 @@ describe('ReceiptContent', () => { }); const waitForData = async () => { + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(mockOrg, mockApp, mockSelectedLayoutSet), ).renderHookResult.result; - - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet), - ).renderHookResult.result; + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(mockOrg, mockApp, mockSelectedLayoutSet)).renderHookResult + .result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); diff --git a/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx b/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx index 72378ef4b41..fcd21ce1ae8 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx +++ b/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx @@ -1,9 +1,14 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; -import { renderHookWithMockStore, renderWithMockStore } from '../testing/mocks'; +import { + formLayoutSettingsMock, + renderHookWithMockStore, + renderWithMockStore, +} from '../testing/mocks'; import { FormDesigner } from './FormDesigner'; import { textMock } from '../../../../testing/mocks/i18nMock'; import { useWidgetsQuery } from '../hooks/queries/useWidgetsQuery'; +import ruleHandlerMock from '../testing/ruleHandlerMock'; // Test data: const org = 'org'; @@ -11,19 +16,22 @@ const app = 'app'; const render = () => { const queries = { - getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('test')) + getFormLayoutSettings: jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), + getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), + getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('test')), }; const props = { selectedLayout: 'test-layout', selectedLayoutSet: 'test-layout-set', }; - return renderWithMockStore({}, queries)( - - ); + return renderWithMockStore({}, queries)(); }; const waitForData = async () => { - const widgetsResult = renderHookWithMockStore()(() => useWidgetsQuery(org, app)).renderHookResult.result; + const widgetsResult = renderHookWithMockStore()(() => useWidgetsQuery(org, app)).renderHookResult + .result; await waitFor(() => expect(widgetsResult.current.isSuccess).toBe(true)); }; @@ -36,6 +44,8 @@ describe('FormDesigner', () => { it('should render the component', async () => { await waitForData(); render(); - await waitFor(() => expect(screen.queryByText(textMock('general.loading'))).not.toBeInTheDocument()); + await waitFor(() => + expect(screen.queryByText(textMock('general.loading'))).not.toBeInTheDocument(), + ); }); }); diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts index dd48d39139c..5ebf18d5459 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts @@ -5,6 +5,7 @@ import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { waitFor } from '@testing-library/react'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { ComponentType } from 'app-shared/types/ComponentType'; +import { externalLayoutsMock } from '../../testing/layoutMock'; // Test data: const org = 'org'; @@ -73,12 +74,18 @@ describe('useAddLayoutMutation', () => { }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts index 1ef4b3d4f79..d56ab5210ac 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts @@ -3,7 +3,7 @@ import { renderHookWithMockStore } from '../../testing/mocks'; import { waitFor } from '@testing-library/react'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useDeleteFormContainerMutation } from './useDeleteFormContainerMutation'; -import { container1IdMock, layout1NameMock } from '../../testing/layoutMock'; +import { container1IdMock, externalLayoutsMock, layout1NameMock } from '../../testing/layoutMock'; // Test data: const org = 'org'; @@ -31,9 +31,11 @@ describe('useDeleteFormContainerMutation', () => { }); const renderDeleteFormContainerMutation = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); return renderHookWithMockStore()(() => useDeleteFormContainerMutation(org, app, selectedLayoutSet), diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts index 06ba4b3c030..302c2eb085b 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts @@ -8,6 +8,7 @@ import { component1IdMock, component2IdMock, container1IdMock, + externalLayoutsMock, layout1NameMock, layoutMock, } from '../../testing/layoutMock'; @@ -53,8 +54,10 @@ describe('useUpdateFormComponentOrderMutation', () => { }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts index 8b8c3245e83..cf89761eb3c 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts @@ -8,7 +8,13 @@ import { useUpdateFormContainerMutation, } from './useUpdateFormContainerMutation'; import { FormContainer } from '../../types/FormContainer'; -import { container1IdMock, layout1Mock, layout1NameMock } from '../../testing/layoutMock'; +import { + container1IdMock, + externalLayoutsMock, + layout1Mock, + layout1NameMock, +} from '../../testing/layoutMock'; +import { ruleConfig as ruleConfigMock } from '../../testing/ruleConfigMock'; // Test data: const org = 'org'; @@ -56,12 +62,16 @@ describe('useUpdateFormContainerMutation', () => { }); const renderAndWaitForData = async () => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; - const ruleConfigResult = renderHookWithMockStore()(() => - useRuleConfigQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getRuleConfig = jest.fn().mockImplementation(() => Promise.resolve(ruleConfigMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; + const ruleConfigResult = renderHookWithMockStore( + {}, + { getRuleConfig }, + )(() => useRuleConfigQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(ruleConfigResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts index 9857d2e6f97..2810551b0c5 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutNameMutation.test.ts @@ -1,5 +1,5 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { renderHookWithMockStore } from '../../testing/mocks'; +import { formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { waitFor } from '@testing-library/react'; @@ -41,12 +41,16 @@ describe('useUpdateLayoutNameMutation', () => { }); const renderAndWaitForData = async () => { + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); const formLayoutsResult = renderHookWithMockStore()(() => useFormLayoutsQuery(org, app, selectedLayoutSet), ).renderHookResult.result; - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts index 6fc91b3df3e..2196fb5cee1 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateLayoutOrderMutation.test.ts @@ -1,5 +1,5 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { renderHookWithMockStore } from '../../testing/mocks'; +import { formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { waitFor } from '@testing-library/react'; import { @@ -70,8 +70,12 @@ describe('useUpdateLayoutOrderMutation', () => { }); const renderAndWaitForData = async () => { - const settingsResult = renderHookWithMockStore()(() => - useFormLayoutSettingsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayoutSettings = jest + .fn() + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + const settingsResult = renderHookWithMockStore( + {}, + { getFormLayoutSettings }, + )(() => useFormLayoutSettingsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(settingsResult.current.isSuccess).toBe(true)); }; diff --git a/frontend/packages/ux-editor/src/hooks/useFormLayoutsSelector.test.ts b/frontend/packages/ux-editor/src/hooks/useFormLayoutsSelector.test.ts index 757a7024a85..15f031fd3d5 100644 --- a/frontend/packages/ux-editor/src/hooks/useFormLayoutsSelector.test.ts +++ b/frontend/packages/ux-editor/src/hooks/useFormLayoutsSelector.test.ts @@ -18,9 +18,11 @@ const selectedLayoutName = 'Side1'; const selectedLayoutSet = 'test-layout-set'; const render = async (callback: () => IFormLayouts | IInternalLayout | IInternalLayoutWithName) => { - const formLayoutsResult = renderHookWithMockStore()(() => - useFormLayoutsQuery(org, app, selectedLayoutSet), - ).renderHookResult.result; + const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const formLayoutsResult = renderHookWithMockStore( + {}, + { getFormLayouts }, + )(() => useFormLayoutsQuery(org, app, selectedLayoutSet)).renderHookResult.result; await waitFor(() => expect(formLayoutsResult.current.isSuccess).toBe(true)); return renderHookWithMockStore()(() => callback()).renderHookResult; diff --git a/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts b/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts index e0b531884d3..bd8b462cf31 100644 --- a/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts +++ b/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts @@ -1,6 +1,10 @@ import { ComponentType } from 'app-shared/types/ComponentType'; import { ErrorCode, useValidateComponent } from './useValidateComponent'; -import { FormCheckboxesComponent, FormComponent, FormRadioButtonsComponent } from '../types/FormComponent'; +import { + FormCheckboxesComponent, + FormComponent, + FormRadioButtonsComponent, +} from '../types/FormComponent'; import { optionListIdsMock, renderHookWithMockStore } from '../testing/mocks'; describe('useValidateComponent', () => { @@ -139,4 +143,10 @@ describe('useValidateComponent', () => { }); }); -const render = (component: FormComponent) => renderHookWithMockStore()(() => useValidateComponent(component)).renderHookResult.result.current; +const render = (component: FormComponent) => { + const queries = { + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + }; + return renderHookWithMockStore({}, queries)(() => useValidateComponent(component)) + .renderHookResult.result.current; +}; From bd0616bf6f3655111179d85b25385df1ed2c96b3 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 20 Dec 2023 16:46:48 +0100 Subject: [PATCH 06/15] Cleanup tests --- .../SelectedSchemaEditor.test.tsx | 10 +- .../TopToolbar/TopToolbar.test.tsx | 9 +- .../components/AppEnvironments.test.tsx | 31 +- .../overview/components/AppLogs.test.tsx | 111 +------ .../overview/components/AppStatus.test.tsx | 48 +-- .../overview/components/Overview.test.tsx | 54 +--- .../features/textEditor/TextEditor.test.tsx | 39 +-- .../hooks/mutations/useBpmnMutation.ts | 2 +- .../hooks/queries/useAppLibVersionQuery.ts | 3 +- .../hooks/queries/useSchemaQuery.test.ts | 27 +- .../SettingsModalButton.test.tsx | 11 - frontend/dashboard/dashboardTestUtils.tsx | 19 +- .../pages/Dashboard/Dashboard.test.tsx | 19 +- frontend/packages/shared/src/api/mutations.ts | 21 +- frontend/packages/shared/src/api/queries.ts | 36 +-- .../VersionControlButtons.test.tsx | 16 +- .../queries/useTextResourcesQuery.test.ts | 14 +- frontend/packages/shared/src/mocks/mocks.ts | 234 ++++++++++++++ .../packages/shared/src/mocks/queriesMock.ts | 289 ++++++++++++------ .../shared/src/types/AppLibVersion.ts | 3 + .../src/components/TextResource.test.tsx | 1 - .../config/EditFormComponent.test.tsx | 3 +- .../config/EditFormContainer.test.tsx | 8 +- .../config/SelectDataModelComponent.test.tsx | 3 +- .../config/editModal/EditCodeList.test.tsx | 8 +- .../editModal/EditDataModelBindings.test.tsx | 2 +- .../src/containers/FormDesigner.test.tsx | 4 +- .../mutations/useAddLayoutMutation.test.ts | 8 +- .../useDeleteFormContainerMutation.test.ts | 5 +- ...seUpdateFormComponentOrderMutation.test.ts | 5 +- .../useUpdateFormContainerMutation.test.ts | 10 +- .../hooks/queries/useRuleModelQuery.test.ts | 19 +- .../src/hooks/useValidateComponent.test.ts | 4 +- .../ServiceContent/ServiceContent.test.tsx | 20 +- .../DeployResourcePage.test.tsx | 61 +--- .../PolicyEditorPage.test.tsx | 6 +- .../ResourceDashboardPage.test.tsx | 56 ++-- .../pages/ResourcePage/ResourcePage.test.tsx | 40 ++- 38 files changed, 691 insertions(+), 568 deletions(-) create mode 100644 frontend/packages/shared/src/mocks/mocks.ts create mode 100644 frontend/packages/shared/src/types/AppLibVersion.ts diff --git a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/SelectedSchemaEditor.test.tsx b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/SelectedSchemaEditor.test.tsx index 1e5374d0d30..508f77c93d1 100644 --- a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/SelectedSchemaEditor.test.tsx +++ b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/SelectedSchemaEditor.test.tsx @@ -24,8 +24,7 @@ jest.mock('@altinn/schema-editor/components/SchemaEditor', () => ({ describe('SelectedSchemaEditor', () => { it('Displays loading spinner while loading', () => { - const getDatamodel = jest.fn().mockImplementation(() => Promise.resolve({})); - render({ getDatamodel }); + render(); expect(screen.getByTitle(textMock('general.loading'))).toBeInTheDocument(); }); @@ -38,8 +37,7 @@ describe('SelectedSchemaEditor', () => { }); it('Renders SchemaEditorApp when finished loading', async () => { - const getDatamodel = jest.fn().mockImplementation(() => Promise.resolve({})); - render({ getDatamodel }); + render(); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); expect(screen.getByTestId(schemaEditorTestId)).toBeInTheDocument(); }); @@ -48,10 +46,10 @@ describe('SelectedSchemaEditor', () => { const render = ( queries: Partial = {}, queryClient = createQueryClientMock(), - props: Partial = {} + props: Partial = {}, ) => renderWithMockStore( {}, queries, - queryClient + queryClient, )(); diff --git a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/TopToolbar/TopToolbar.test.tsx b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/TopToolbar/TopToolbar.test.tsx index b6acabf2cd3..0c06394feea 100644 --- a/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/TopToolbar/TopToolbar.test.tsx +++ b/frontend/app-development/features/dataModelling/SchemaEditorWithToolbar/TopToolbar/TopToolbar.test.tsx @@ -12,6 +12,7 @@ import { convertMetadataToOption } from '../../../../utils/metadataUtils'; import { buildJsonSchema } from '@altinn/schema-model'; import { renderWithMockStore } from '../../../../test/mocks'; import { useQueryClient } from '@tanstack/react-query'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const user = userEvent.setup(); @@ -44,7 +45,6 @@ const defaultProps: TopToolbarProps = { }; const org = 'org'; const app = 'app'; -const generateModels = jest.fn().mockImplementation(() => Promise.resolve()); const modelPath = jsonMetadata1Mock.repositoryRelativeUrl; const renderToolbar = ( @@ -60,10 +60,7 @@ const renderToolbar = ( return ; }; - return renderWithMockStore( - {}, - { generateModels, ...servicesContextProps }, - )(); + return renderWithMockStore({}, { ...servicesContextProps })(); }; // Mocks: @@ -93,7 +90,7 @@ describe('TopToolbar', () => { const generateButton = screen.getByRole('button', { name: generateText }); expect(generateButton).toBeDefined(); await act(() => user.click(generateButton)); - expect(generateModels).toHaveBeenCalledTimes(1); + expect(queriesMock.generateModels).toHaveBeenCalledTimes(1); }); it('Does not show any error by default', () => { diff --git a/frontend/app-development/features/overview/components/AppEnvironments.test.tsx b/frontend/app-development/features/overview/components/AppEnvironments.test.tsx index f4cc86ece57..5ba72ba89fe 100644 --- a/frontend/app-development/features/overview/components/AppEnvironments.test.tsx +++ b/frontend/app-development/features/overview/components/AppEnvironments.test.tsx @@ -4,6 +4,7 @@ import { AppEnvironments } from './AppEnvironments'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; import { textMock } from '../../../../testing/mocks/i18nMock'; +import { appDeployment, deployEnvironment } from 'app-shared/mocks/mocks'; // Test data const org = 'org'; @@ -18,10 +19,7 @@ const render = (queries = {}) => { describe('AppEnvironments', () => { it('shows loading spinner when loading required data', () => { - render({ - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), - getOrgList: jest.fn().mockImplementation(() => Promise.resolve([])), - }); + render(); expect(screen.getByText(textMock('general.loading'))).toBeInTheDocument(); }); @@ -38,10 +36,7 @@ describe('AppEnvironments', () => { }); it('shows no environments message when organization has no environment', async () => { - render({ - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), - getOrgList: jest.fn().mockImplementation(() => Promise.resolve({ orgs: [] })), - }); + render(); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); @@ -54,26 +49,17 @@ describe('AppEnvironments', () => { it('shows statuses when organization has environments', async () => { const envName = 'tt02'; - const envType = 'test'; render({ getDeployments: jest.fn().mockImplementation(() => Promise.resolve({ results: [ { - tagName: '1', + ...appDeployment, envName, - deployedInEnv: false, build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', + ...appDeployment.build, finished: '2023-10-03T09:57:41.29Z', }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), @@ -82,13 +68,8 @@ describe('AppEnvironments', () => { getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([ { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', + ...deployEnvironment, name: envName, - type: envType, }, ]), ), diff --git a/frontend/app-development/features/overview/components/AppLogs.test.tsx b/frontend/app-development/features/overview/components/AppLogs.test.tsx index 08fe25a4f88..2914dbd1615 100644 --- a/frontend/app-development/features/overview/components/AppLogs.test.tsx +++ b/frontend/app-development/features/overview/components/AppLogs.test.tsx @@ -4,6 +4,7 @@ import { AppLogs } from './AppLogs'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; import { textMock } from '../../../../testing/mocks/i18nMock'; +import { appDeployment, deployEnvironment } from 'app-shared/mocks/mocks'; // Test data const org = 'ttd'; @@ -18,9 +19,7 @@ const render = (queries = {}) => { describe('AppLogs', () => { it('shows loading spinner when loading required data', () => { - render({ - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), - }); + render(); expect(screen.getByText(textMock('general.loading'))).toBeInTheDocument(); }); @@ -41,36 +40,14 @@ describe('AppLogs', () => { Promise.resolve({ results: [ { + ...appDeployment, tagName: '2', envName: 'production', - deployedInEnv: true, - build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: '2023-10-03T09:57:41.29Z', - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, { + ...appDeployment, tagName: '1', envName: 'tt02', - deployedInEnv: true, - build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: '2023-10-03T09:57:41.29Z', - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), @@ -78,41 +55,15 @@ describe('AppLogs', () => { getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([ { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', + ...deployEnvironment, name: 'production', type: 'production', }, { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', + ...deployEnvironment, name: 'tt02', type: 'test', }, - { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', - name: 'at21', - type: 'test', - }, - { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', - name: 'at22', - type: 'test', - }, ]), ), }); @@ -142,62 +93,14 @@ describe('AppLogs', () => { Promise.resolve({ results: [ { - tagName: '2', - envName: 'production', - deployedInEnv: true, + ...appDeployment, build: { - id: '14381045', - status: 'completed', result: '', - started: '2023-10-03T09:57:31.238Z', - finished: '2023-10-03T09:57:41.29Z', - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, - }, - { - tagName: '1', - envName: 'tt02', - deployedInEnv: true, - build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: null, }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), ), - getEnvironments: jest.fn().mockImplementation(() => - Promise.resolve([ - { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', - name: 'production', - type: 'production', - }, - { - appsUrl: 'http://host.docker.internal:6161', - platformUrl: 'http://host.docker.internal:6161', - hostname: 'host.docker.internal:6161', - appPrefix: 'apps', - platformPrefix: 'platform', - name: 'tt02', - type: 'test', - }, - ]), - ), }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); diff --git a/frontend/app-development/features/overview/components/AppStatus.test.tsx b/frontend/app-development/features/overview/components/AppStatus.test.tsx index c6a349eaf3f..79285f81577 100644 --- a/frontend/app-development/features/overview/components/AppStatus.test.tsx +++ b/frontend/app-development/features/overview/components/AppStatus.test.tsx @@ -4,6 +4,7 @@ import { AppStatus } from './AppStatus'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; import { textMock } from '../../../../testing/mocks/i18nMock'; +import { appDeployment } from 'app-shared/mocks/mocks'; // Test data const org = 'ttd'; @@ -44,20 +45,8 @@ describe('AppStatus', () => { Promise.resolve({ results: [ { - tagName: '1', - envName: envNameProduction, + ...appDeployment, deployedInEnv: true, - build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: '2023-10-03T09:57:41.29Z', - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), @@ -80,20 +69,9 @@ describe('AppStatus', () => { Promise.resolve({ results: [ { - tagName: '1', + ...appDeployment, envName: envNameTest, deployedInEnv: true, - build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: '2023-10-03T09:57:41.29Z', - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), @@ -108,13 +86,7 @@ describe('AppStatus', () => { }); it('shows no app alert when application not deployed', async () => { - render({ - getDeployments: jest.fn().mockImplementation(() => - Promise.resolve({ - results: [], - }), - ), - }); + render(); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); @@ -129,20 +101,12 @@ describe('AppStatus', () => { Promise.resolve({ results: [ { - tagName: '1', + ...appDeployment, envName: envNameTest, - deployedInEnv: false, build: { - id: '14381045', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', + ...appDeployment.build, finished: '2023-10-03T09:57:41.29Z', }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, }, ], }), diff --git a/frontend/app-development/features/overview/components/Overview.test.tsx b/frontend/app-development/features/overview/components/Overview.test.tsx index 69ee5ad0e05..13431fbee2c 100644 --- a/frontend/app-development/features/overview/components/Overview.test.tsx +++ b/frontend/app-development/features/overview/components/Overview.test.tsx @@ -16,8 +16,6 @@ describe('Overview', () => { }); it('renders component', async () => { render({ - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), - getOrgList: jest.fn().mockImplementation(() => Promise.resolve({ orgs: [] })), getAppConfig: jest.fn().mockImplementation(() => Promise.resolve({ serviceName: title, @@ -44,14 +42,6 @@ describe('Overview', () => { it('should display AppLogs if environments exist', async () => { render({ - getAppConfig: jest.fn().mockImplementation(() => - Promise.resolve({ - repositoryName: app, - serviceName: app, - serviceId: null, - serviceDescription: null, - }), - ), getOrgList: jest.fn().mockImplementation(() => Promise.resolve({ orgs: { @@ -61,41 +51,6 @@ describe('Overview', () => { }, }), ), - getDeployments: jest.fn().mockImplementation(() => - Promise.resolve({ - results: [ - { - tagName: '1', - envName: 'test', - deployedInEnv: true, - build: { - id: '1', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: null, - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, - }, - ], - }), - ), - getEnvironments: jest.fn().mockImplementation(() => - Promise.resolve([ - { - appsUrl: '', - platformUrl: '', - hostname: '', - appPrefix: '', - platformPrefix: '', - name: '', - type: '', - }, - ]), - ), }); expect( await screen.findByRole('heading', { name: textMock('overview.activity') }), @@ -103,14 +58,7 @@ describe('Overview', () => { }); it('should not display AppLogs if environments do not exist', async () => { - render({ - getAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), - getOrgList: jest.fn().mockImplementation(() => - Promise.resolve({ - orgs: {}, - }), - ), - }); + render(); expect( screen.queryByRole('heading', { name: textMock('overview.activity') }), ).not.toBeInTheDocument(); diff --git a/frontend/app-development/features/textEditor/TextEditor.test.tsx b/frontend/app-development/features/textEditor/TextEditor.test.tsx index 6c9e4d27892..aa1242afc12 100644 --- a/frontend/app-development/features/textEditor/TextEditor.test.tsx +++ b/frontend/app-development/features/textEditor/TextEditor.test.tsx @@ -7,6 +7,7 @@ import { textMock } from '../../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import userEvent from '@testing-library/user-event'; import * as testids from '../../../testing/testids'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; // Test data const org = 'test-org'; @@ -58,29 +59,25 @@ describe('TextEditor', () => { it('adds new text resource when clicking add button', async () => { const user = userEvent.setup(); - const upsertTextResources = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ upsertTextResources }); + await render(); const addButton = screen.getByRole('button', { name: textMock('text_editor.new_text') }); await act(() => user.click(addButton)); - expect(upsertTextResources).toHaveBeenCalledTimes(2); + expect(queriesMock.upsertTextResources).toHaveBeenCalledTimes(2); }); it('updates text resource when editing text', async () => { const user = userEvent.setup(); - const upsertTextResources = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ upsertTextResources }); + await render(); const textarea = screen.getByRole('textbox', { name: 'nb translation' }); await act(() => user.clear(textarea)); await act(() => user.type(textarea, 'test')); await act(() => user.tab()); - expect(upsertTextResources).toHaveBeenCalledWith(org, app, 'nb', { + expect(queriesMock.upsertTextResources).toHaveBeenCalledWith(org, app, 'nb', { [testTextResourceKey]: 'test', }); }); @@ -88,9 +85,7 @@ describe('TextEditor', () => { it('updates text id when editing text id', async () => { const user = userEvent.setup(); - const updateTextId = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ updateTextId }); + await render(); const editButton = screen.getByRole('button', { name: 'toggle-textkey-edit' }); await act(() => editButton.click()); @@ -100,7 +95,7 @@ describe('TextEditor', () => { await act(() => user.type(textarea, 'test')); await act(() => user.tab()); - expect(updateTextId).toHaveBeenCalledWith(org, app, [ + expect(queriesMock.updateTextId).toHaveBeenCalledWith(org, app, [ { newId: 'test', oldId: testTextResourceKey }, ]); }); @@ -108,9 +103,7 @@ describe('TextEditor', () => { it('deletes text id when clicking delete button', async () => { const user = userEvent.setup(); - const updateTextId = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ updateTextId }); + await render(); const deleteButton = screen.getByRole('button', { name: textMock('schema_editor.delete') }); await act(() => deleteButton.click()); @@ -120,15 +113,15 @@ describe('TextEditor', () => { }); await act(() => user.click(confirmButton)); - expect(updateTextId).toHaveBeenCalledWith(org, app, [{ oldId: testTextResourceKey }]); + expect(queriesMock.updateTextId).toHaveBeenCalledWith(org, app, [ + { oldId: testTextResourceKey }, + ]); }); it('adds new language when clicking add button', async () => { const user = userEvent.setup(); - const addLanguageCode = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ addLanguageCode }); + await render(); const addBtn = screen.getByRole('button', { name: /legg til/i, @@ -142,7 +135,7 @@ describe('TextEditor', () => { expect(addBtn).not.toBeDisabled(); await act(() => user.click(addBtn)); - expect(addLanguageCode).toHaveBeenCalledWith(org, app, 'se', { + expect(queriesMock.addLanguageCode).toHaveBeenCalledWith(org, app, 'se', { language: 'se', resources: [{ id: testTextResourceKey, value: '' }], }); @@ -151,9 +144,7 @@ describe('TextEditor', () => { it('deletes a language when clicking delete button', async () => { const user = userEvent.setup(); - const deleteLanguageCode = jest.fn().mockImplementation(() => Promise.resolve()); - - await render({ deleteLanguageCode }); + await render(); const deleteButton = screen.getByTestId(testids.deleteButton('en')); await act(() => user.click(deleteButton)); @@ -163,7 +154,7 @@ describe('TextEditor', () => { }); await act(() => user.click(confirmButton)); - expect(deleteLanguageCode).toHaveBeenCalledWith(org, app, 'en'); + expect(queriesMock.deleteLanguageCode).toHaveBeenCalledWith(org, app, 'en'); await waitFor(() => expect(screen.queryByRole('dialog')).not.toBeInTheDocument()); }); diff --git a/frontend/app-development/hooks/mutations/useBpmnMutation.ts b/frontend/app-development/hooks/mutations/useBpmnMutation.ts index 95bb6b2ddc8..2059634fdb3 100644 --- a/frontend/app-development/hooks/mutations/useBpmnMutation.ts +++ b/frontend/app-development/hooks/mutations/useBpmnMutation.ts @@ -1,5 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { updateBpmnXml } from 'app-shared/api/queries'; +import { updateBpmnXml } from 'app-shared/api/mutations'; import { QueryKey } from 'app-shared/types/QueryKey'; type UseBpmnMutationPayload = { diff --git a/frontend/app-development/hooks/queries/useAppLibVersionQuery.ts b/frontend/app-development/hooks/queries/useAppLibVersionQuery.ts index 744b09bd3c3..ae91b27ed95 100644 --- a/frontend/app-development/hooks/queries/useAppLibVersionQuery.ts +++ b/frontend/app-development/hooks/queries/useAppLibVersionQuery.ts @@ -1,5 +1,6 @@ import { useQuery } from '@tanstack/react-query'; import { getAppLibVersion } from 'app-shared/api/queries'; +import { AppLibVersion } from 'app-shared/types/AppLibVersion'; import { QueryKey } from 'app-shared/types/QueryKey'; /** @@ -11,7 +12,7 @@ import { QueryKey } from 'app-shared/types/QueryKey'; * @returns UseQueryResult with the version */ export const useAppLibVersionQuery = (org: string, repo: string) => { - return useQuery<{ version: string }>({ + return useQuery({ queryKey: [QueryKey.AppLibVersion, org, repo], queryFn: () => getAppLibVersion(org, repo), }); diff --git a/frontend/app-development/hooks/queries/useSchemaQuery.test.ts b/frontend/app-development/hooks/queries/useSchemaQuery.test.ts index 742f5c2bca0..1297d20f377 100644 --- a/frontend/app-development/hooks/queries/useSchemaQuery.test.ts +++ b/frontend/app-development/hooks/queries/useSchemaQuery.test.ts @@ -2,13 +2,12 @@ import { waitFor } from '@testing-library/react'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { useSchemaQuery } from './useSchemaQuery'; import { renderHookWithMockStore } from '../../test/mocks'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; // Test data: const jsonModelPathWithSlash = '/App/models/model.schema.json'; const xsdModelPath = 'App/models/model.xsd'; const xsdModelPathWithSlash = '/' + xsdModelPath; -const getDatamodel = jest.fn().mockImplementation(() => Promise.resolve({})); -const addXsdFromRepo = jest.fn().mockImplementation(() => Promise.resolve({})); const org = 'org'; const app = 'app'; @@ -16,26 +15,30 @@ describe('useSchemaQuery', () => { afterEach(jest.clearAllMocks); it('Calls getDatamodel with correct arguments when Json Schema', async () => { - const { renderHookResult: { result } } = renderHookWithMockStore( + const { + renderHookResult: { result }, + } = renderHookWithMockStore( + {}, {}, - { getDatamodel, addXsdFromRepo }, createQueryClientMock(), )(() => useSchemaQuery(jsonModelPathWithSlash)); await waitFor(() => expect(result.current.isSuccess).toBe(true)); - expect(getDatamodel).toHaveBeenCalledTimes(1); - expect(getDatamodel).toHaveBeenCalledWith(org, app, jsonModelPathWithSlash); - expect(addXsdFromRepo).not.toHaveBeenCalled(); + expect(queriesMock.getDatamodel).toHaveBeenCalledTimes(1); + expect(queriesMock.getDatamodel).toHaveBeenCalledWith(org, app, jsonModelPathWithSlash); + expect(queriesMock.addXsdFromRepo).not.toHaveBeenCalled(); }); it('Calls addXsdFromRepo with correct arguments when XSD', async () => { - const { renderHookResult: { result } } = renderHookWithMockStore( + const { + renderHookResult: { result }, + } = renderHookWithMockStore( + {}, {}, - { getDatamodel, addXsdFromRepo }, createQueryClientMock(), )(() => useSchemaQuery(xsdModelPathWithSlash)); await waitFor(() => expect(result.current.isSuccess).toBe(true)); - expect(addXsdFromRepo).toHaveBeenCalledTimes(1); - expect(addXsdFromRepo).toHaveBeenCalledWith(org, app, xsdModelPath); - expect(getDatamodel).not.toHaveBeenCalled(); + expect(queriesMock.addXsdFromRepo).toHaveBeenCalledTimes(1); + expect(queriesMock.addXsdFromRepo).toHaveBeenCalledWith(org, app, xsdModelPath); + expect(queriesMock.getDatamodel).not.toHaveBeenCalled(); }); }); diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModalButton.test.tsx b/frontend/app-development/layout/SettingsModalButton/SettingsModalButton.test.tsx index c3c2a60c261..4f18f8ac2ad 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModalButton.test.tsx +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModalButton.test.tsx @@ -12,12 +12,6 @@ import { MemoryRouter } from 'react-router-dom'; const mockApp: string = 'app'; const mockOrg: string = 'org'; -const getAppPolicy = jest.fn().mockImplementation(() => Promise.resolve({})); -const getAppConfig = jest.fn().mockImplementation(() => Promise.resolve({})); -const getRepoMetadata = jest.fn().mockImplementation(() => Promise.resolve({})); -const getRepoInitialCommit = jest.fn().mockImplementation(() => Promise.resolve({})); -const getAppMetadata = jest.fn().mockImplementation(() => Promise.resolve({})); - const defaultProps: SettingsModalButtonProps = { org: mockOrg, app: mockApp, @@ -85,11 +79,6 @@ const render = ( ) => { const allQueries: ServicesContextProps = { ...queriesMock, - getAppPolicy, - getAppConfig, - getRepoMetadata, - getRepoInitialCommit, - getAppMetadata, ...queries, }; return rtlRender( diff --git a/frontend/dashboard/dashboardTestUtils.tsx b/frontend/dashboard/dashboardTestUtils.tsx index 2b72a1f0015..3762d3c6e88 100644 --- a/frontend/dashboard/dashboardTestUtils.tsx +++ b/frontend/dashboard/dashboardTestUtils.tsx @@ -1,14 +1,12 @@ import { QueryClient } from '@tanstack/react-query'; -import { IRepository } from 'app-shared/types/global'; import React, { ReactNode } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider, - ServicesContextProviderProps + ServicesContextProviderProps, } from 'app-shared/contexts/ServicesContext'; import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { AddRepoParams, SearchRepoFilterParams, SearchRepositoryResponse } from 'app-shared/types/api'; import { queryClientConfigMock, createQueryClientMock } from 'app-shared/mocks/queryClientMock'; export type MockServicesContextWrapperProps = { @@ -24,25 +22,14 @@ export const MockServicesContextWrapper = ({ }: MockServicesContextWrapperProps) => { const queries: ServicesContextProviderProps = { ...queriesMock, - getUser: () => Promise.resolve({ avatar_url: null, email: '', full_name: '', id: null, login: null }), - logout: () => Promise.resolve(), - getOrganizations: () => Promise.resolve([]), - addRepo: (repoToAdd: AddRepoParams) => Promise.resolve({} as IRepository), - copyApp: () => Promise.resolve(), - getStarredRepos: () => Promise.resolve([] as IRepository[]), - searchRepos: (params: SearchRepoFilterParams) => Promise.resolve({} as SearchRepositoryResponse), - setStarredRepo: () => Promise.resolve([]), - unsetStarredRepo: () => Promise.resolve(), ...customServices, client, - clientConfig: queryClientConfigMock + clientConfig: queryClientConfigMock, }; return ( - - {children} - + {children} ); }; diff --git a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx index daa1f297c5c..f0244f38427 100644 --- a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx +++ b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx @@ -13,38 +13,41 @@ const renderWithMockServices = (services?: Partial) => { render( - + , ); }; -jest.mock("react-router-dom", () => ({ - ...jest.requireActual("react-router-dom"), +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), useParams: () => ({ - selectedContext: SelectedContextType.Self + selectedContext: SelectedContextType.Self, }), })); describe('Dashboard', () => { - test('should display spinner while loading starred repositories', () => { renderWithMockServices(); expect(screen.getByText(textMock('general.loading'))).toBeInTheDocument(); }); test('should display no favorites when starred repos is empty', async () => { - renderWithMockServices({ getStarredRepos: () => Promise.resolve([]) }); + renderWithMockServices(); expect(await screen.findByText(textMock('dashboard.no_repos_result'))).toBeInTheDocument(); }); test('should display favorite list with one item', async () => { renderWithMockServices({ getStarredRepos: () => Promise.resolve([starredRepoMock]) }); await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); - expect(await screen.findAllByRole('menuitem', { name: textMock('dashboard.unstar') })).toHaveLength(1); + expect( + await screen.findAllByRole('menuitem', { name: textMock('dashboard.unstar') }), + ).toHaveLength(1); }); test('should display list of my application', async () => { renderWithMockServices({ searchRepos: () => Promise.resolve(searchedRepos) }); await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); - expect(await screen.findAllByRole('menuitem', { name: textMock('dashboard.star') })).toHaveLength(1); + expect( + await screen.findAllByRole('menuitem', { name: textMock('dashboard.star') }), + ).toHaveLength(1); }); }); diff --git a/frontend/packages/shared/src/api/mutations.ts b/frontend/packages/shared/src/api/mutations.ts index 48b8cfae630..490059ec206 100644 --- a/frontend/packages/shared/src/api/mutations.ts +++ b/frontend/packages/shared/src/api/mutations.ts @@ -30,6 +30,7 @@ import { appMetadataPath, serviceConfigPath, importResourceFromAltinn2Path, + processEditorPath, } from 'app-shared/api/paths'; import { AddLanguagePayload } from 'app-shared/types/api/AddLanguagePayload'; import { AddRepoParams } from 'app-shared/types/api'; @@ -60,11 +61,11 @@ export const addLanguageCode = (org: string, app: string, language: string, payl export const addLayoutSet = (org: string, app: string, payload: LayoutSetConfig) => put(layoutSetsPath(org, app), payload); export const addRepo = (repoToAdd: AddRepoParams) => post(`${createRepoPath()}${buildQueryParams(repoToAdd)}`); export const addXsdFromRepo = (org: string, app: string, modelPath: string) => post(datamodelAddXsdFromRepoPath(org, app, modelPath)); +export const commitAndPushChanges = (org: string, app: string, payload: CreateRepoCommitPayload) => post(repoCommitPushPath(org, app), payload, { headers }); +export const configureLayoutSet = (org: string, app: string, layoutSetName: string) => post(layoutSetPath(org, app, layoutSetName)); export const copyApp = (org: string, app: string, repoName: string) => post(copyAppPath(org, app, repoName)); export const createDatamodel = (org: string, app: string, payload: CreateDatamodelPayload) => post(createDatamodelPath(org, app), payload); export const createDeployment = (org: string, app: string, payload: CreateDeploymentPayload) => post(deploymentsPath(org, app), payload); -export const commitAndPushChanges = (org: string, app: string, payload: CreateRepoCommitPayload) => post(repoCommitPushPath(org, app), payload, { headers }); -export const configureLayoutSet = (org: string, app: string, layoutSetName: string) => post(layoutSetPath(org, app, layoutSetName)); export const createRelease = (org: string, app: string, payload: CreateReleasePayload) => post(releasesPath(org, app), payload); export const createRepoCommit = (org: string, app: string, payload: CreateRepoCommitPayload) => post(repoCommitPath(org, app), payload, { headers }); export const deleteAppAttachmentMetadata = (org: string, app: string, id: string) => del(appMetadataAttachmentPath(org, app), { headers, data: id }); @@ -85,14 +86,22 @@ export const updateAppAttachmentMetadata = (org: string, app: string, payload: A export const updateFormLayoutName = (org: string, app: string, oldName: string, newName: string, layoutSetName: string) => post(formLayoutNamePath(org, app, oldName, layoutSetName), JSON.stringify(newName), { headers: { 'Content-Type': 'application/json' } }); export const updateTextId = (org: string, app: string, payload: UpdateTextIdPayload) => put(textResourceIdsPath(org, app), payload); export const updateTranslationByLangCode = (org: string, app: string, language, payload) => post(textResourcesPath(org, app, language), payload); -export const upsertTextResources = (org: string, app: string, language: string, payload: ITextResourcesObjectFormat) => put(textResourcesPath(org, app, language), payload); export const updateAppPolicy = (org: string, app: string, payload: Policy) => put(appPolicyPath(org, app), payload); export const updateAppMetadata = (org: string, app: string, payload: ApplicationMetadata) => put(appMetadataPath(org, app), payload); export const updateAppConfig = (org: string, app: string, payload: AppConfig) => post(serviceConfigPath(org, app), payload); +export const upsertTextResources = (org: string, app: string, language: string, payload: ITextResourcesObjectFormat) => put(textResourcesPath(org, app, language), payload); // Resourceadm -export const updatePolicy = (org: string, repo: string, id: string, payload: Policy) => put(resourcePolicyPath(org, repo, id), payload); export const createResource = (org: string, payload: NewResource) => post(resourceCreatePath(org), payload); -export const updateResource = (org: string, repo: string, payload: Resource) => put(resourceEditPath(org, repo), payload); -export const publishResource = (org: string, repo: string, id: string, env: string) => post(publishResourcePath(org, repo, id, env), { headers: { 'Content-Type': 'application/json' } }); export const importResourceFromAltinn2 = (org: string, environment: string, serviceCode: string, serviceEdition: string) => post(importResourceFromAltinn2Path(org, environment, serviceCode, serviceEdition)); +export const publishResource = (org: string, repo: string, id: string, env: string) => post(publishResourcePath(org, repo, id, env), { headers: { 'Content-Type': 'application/json' } }); +export const updatePolicy = (org: string, repo: string, id: string, payload: Policy) => put(resourcePolicyPath(org, repo, id), payload); +export const updateResource = (org: string, repo: string, payload: Resource) => put(resourceEditPath(org, repo), payload); + +// ProcessEditor +export const updateBpmnXml = (org: string, app: string, bpmnXml: string) => + put(processEditorPath(org, app), bpmnXml, { + headers: { + 'Content-Type': 'application/xml', + }, + }); diff --git a/frontend/packages/shared/src/api/queries.ts b/frontend/packages/shared/src/api/queries.ts index d11f9a933a6..1711f7aa980 100644 --- a/frontend/packages/shared/src/api/queries.ts +++ b/frontend/packages/shared/src/api/queries.ts @@ -1,4 +1,4 @@ -import { get, put } from 'app-shared/utils/networking'; +import { get } from 'app-shared/utils/networking'; import { altinn2LinkServicesPath, appLibVersionPath, @@ -67,9 +67,12 @@ import type { Commit } from 'app-shared/types/Commit'; import type { ApplicationMetadata } from 'app-shared/types/ApplicationMetadata'; import { Altinn2LinkService } from 'app-shared/types/Altinn2LinkService'; import { NewsList } from 'app-shared/types/api/NewsList'; +import { AppLibVersion } from 'app-shared/types/AppLibVersion'; export const getAppReleases = (owner: string, app: string) => get(releasesPath(owner, app, 'Descending')); export const getBranchStatus = (owner: string, app: string, branch: string) => get(branchStatusPath(owner, app, branch)); +export const getComponentSchema = (component: string) => get(componentSchemaUrl(component)); +export const getComponentsCommonDefsSchema = () => get(componentSchemaUrl('common-defs')); export const getDatamodel = (owner: string, app: string, modelPath: string) => get(datamodelPath(owner, app, modelPath)); export const getDatamodelMetadata = (owner: string, app: string) => get(datamodelMetadataPath(owner, app)); export const getDatamodelsJson = (owner: string, app: string) => get(datamodelsPath(owner, app)); @@ -77,12 +80,16 @@ export const getDatamodelsXsd = (owner: string, app: string) => get get(deployPermissionsPath(owner, app)); export const getDeployments = (owner: string, app: string) => get(deploymentsPath(owner, app, 'Descending')); export const getEnvironments = () => get(envConfigPath()); +export const getExpressionSchema = () => get(expressionSchemaUrl()); export const getFormLayoutSettings = (owner: string, app: string, layoutSetName: string) => get(layoutSettingsPath(owner, app, layoutSetName)); export const getFormLayouts = (owner: string, app: string, layoutSetName: string) => get(formLayoutsPath(owner, app, layoutSetName)); export const getFrontEndSettings = (owner: string, app: string) => get(frontEndSettingsPath(owner, app)); -export const getLayoutSets = (owner: string, app: string) => get(layoutSetsPath(owner, app)); export const getInstanceIdForPreview = (owner: string, app: string) => get(instanceIdForPreviewPath(owner, app)); +export const getLayoutSchema = () => get(layoutSchemaUrl()); +export const getLayoutSets = (owner: string, app: string) => get(layoutSetsPath(owner, app)); export const getNewsList = (language: 'nb' | 'en') => get(newsListUrl(language)); +export const getNumberFormatSchema = () => get(numberFormatSchemaUrl()); +export const getOptionListIds = (owner: string, app: string) => get(optionListIdsPath(owner, app)); export const getOrgList = () => get(orgsListUrl()); export const getOrganizations = () => get(orgsListPath()); export const getRepoInitialCommit = (owner: string, app: string) => get(repoInitialCommitPath(owner, app)); @@ -90,20 +97,13 @@ export const getRepoMetadata = (owner: string, app: string) => get(r export const getRepoPull = (owner: string, app: string) => get(repoPullPath(owner, app)); export const getRepoStatus = (owner: string, app: string) => get(repoStatusPath(owner, app)); export const getRuleConfig = (owner: string, app: string, layoutSetName: string) => get(ruleConfigPath(owner, app, layoutSetName)); -export const getRuleModel = (owner: string, app: string, layoutSetName: string) => get(ruleHandlerPath(owner, app, layoutSetName)); +export const getRuleModel = (owner: string, app: string, layoutSetName: string) => get(ruleHandlerPath(owner, app, layoutSetName)); export const getStarredRepos = () => get(userStarredListPath()); export const getTextLanguages = (owner: string, app: string): Promise => get(textLanguagesPath(owner, app)); export const getTextResources = (owner: string, app: string, lang: string) => get(textResourcesPath(owner, app, lang)); export const getUser = () => get(userCurrentPath()); export const getWidgetSettings = (owner: string, app: string) => get(widgetSettingsPath(owner, app)); export const searchRepos = (filter: SearchRepoFilterParams) => get(`${repoSearchPath()}${buildQueryParams(filter)}`); -export const getOptionListIds = (owner: string, app: string) => get(optionListIdsPath(owner, app)); - -export const getExpressionSchema = () => get(expressionSchemaUrl()); -export const getLayoutSchema = () => get(layoutSchemaUrl()); -export const getNumberFormatSchema = () => get(numberFormatSchemaUrl()); -export const getComponentSchema = (component: string) => get(componentSchemaUrl(component)); -export const getComponentsCommonDefsSchema = () => get(componentSchemaUrl('common-defs')); // Settings modal export const getAppConfig = (org: string, app: string) => get(serviceConfigPath(org, app)); @@ -111,22 +111,16 @@ export const getAppPolicy = (org: string, app: string) => get(appPolicyP export const getAppMetadata = (org: string, app: string) => get(appMetadataPath(org, app)); // Resourceadm +export const getAltinn2LinkServices = (org: string, environment: string) => get(altinn2LinkServicesPath(org, environment)); export const getPolicyActions = (org: string, repo: string) => get(resourceActionsPath(org, repo)); export const getPolicy = (org: string, repo: string, id: string) => get(resourcePolicyPath(org, repo, id)); export const getPolicySubjects = (org: string, repo: string) => get(resourceSubjectsPath(org, repo)); -export const getResourcePublishStatus = (org: string, repo: string, id: string) => get(resourcePublishStatusPath(org, repo, id)); -export const getResourceList = (org: string) => get(resourceListPath(org)); export const getResource = (org: string, repo: string, id: string) => get(resourceSinglePath(org, repo, id)); +export const getResourceList = (org: string) => get(resourceListPath(org)); +export const getResourcePublishStatus = (org: string, repo: string, id: string) => get(resourcePublishStatusPath(org, repo, id)); export const getValidatePolicy = (org: string, repo: string, id: string) => get(resourceValidatePolicyPath(org, repo, id)); export const getValidateResource = (org: string, repo: string, id: string) => get(resourceValidateResourcePath(org, repo, id)); -export const getAltinn2LinkServices = (org: string, environment: string) => get(altinn2LinkServicesPath(org, environment)); // ProcessEditor -export const getBpmnFile = (org: string, app: string) => get(processEditorPath(org, app)); -export const updateBpmnXml = (org: string, app: string, bpmnXml: string) => - put(processEditorPath(org, app), bpmnXml, { - headers: { - 'Content-Type': 'application/xml', - }, - }); -export const getAppLibVersion = (org: string, app: string) => get(appLibVersionPath(org, app)); +export const getAppLibVersion = (org: string, app: string) => get(appLibVersionPath(org, app)); +export const getBpmnFile = (org: string, app: string) => get(processEditorPath(org, app)); diff --git a/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx b/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx index 096b62ec74d..2094e0096f6 100644 --- a/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx +++ b/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx @@ -8,6 +8,7 @@ import userEvent from '@testing-library/user-event'; import type { RepoStatus } from 'app-shared/types/RepoStatus'; import { queryClientMock } from 'app-shared/mocks/queryClientMock'; import * as testids from '../../../../../../testing/testids'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const user = userEvent.setup(); const org = 'test-org'; @@ -51,13 +52,11 @@ const mergeConflictRepoStatus: RepoStatus = { repositoryStatus: 'CheckoutConflict', }; -const getRepoMetadata = jest.fn().mockImplementation(() => Promise.resolve({})); const getRepoStatus = jest.fn().mockImplementation(() => Promise.resolve(okRepoStatus)); const getRepoPull = jest.fn().mockImplementation(() => Promise.resolve(okRepoStatus)); const commitAndPushChanges = jest.fn().mockImplementation(() => Promise.resolve(okRepoStatus)); const defaultQueries: Partial = { - getRepoMetadata, getRepoStatus, getRepoPull, commitAndPushChanges, @@ -74,7 +73,7 @@ describe('Shared > Version Control > VersionControlHeader', () => { it('should render header when type is not defined', async () => { render(); - await waitFor(() => expect(getRepoMetadata).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(queriesMock.getRepoMetadata).toHaveBeenCalledTimes(1)); expect(await screen.findByTestId(testids.versionControlHeader)).not.toBeNull(); }); @@ -82,7 +81,7 @@ describe('Shared > Version Control > VersionControlHeader', () => { render(); const fetchButton = screen.getByRole('button', { name: textMock('sync_header.fetch_changes') }); await act(() => user.click(fetchButton)); - await waitFor(() => expect(getRepoMetadata).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(queriesMock.getRepoMetadata).toHaveBeenCalledTimes(1)); await waitFor(() => expect(getRepoStatus).toHaveBeenCalledTimes(1)); await waitFor(() => expect(getRepoPull).toHaveBeenCalledTimes(1)); }); @@ -220,7 +219,12 @@ const render = ( queries: Partial = {}, ) => renderRtl( - - + + , ); diff --git a/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts b/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts index 825b45b8d59..1f75ede4724 100644 --- a/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts +++ b/frontend/packages/shared/src/hooks/queries/useTextResourcesQuery.test.ts @@ -12,12 +12,16 @@ const app = 'app'; describe('useTextResourcesQuery', () => { it('Calls getTextResources for each language', async () => { - const { result: resourcesResult } = renderHookWithMockStore()(() => - useTextResourcesQuery(org, app), - ).renderHookResult; + const getTextLanguages = jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)); + const { result: resourcesResult } = renderHookWithMockStore( + {}, + { + getTextLanguages, + }, + )(() => useTextResourcesQuery(org, app)).renderHookResult; await waitFor(() => expect(resourcesResult.current.isSuccess).toBe(true)); - expect(queriesMock.getTextLanguages).toHaveBeenCalledTimes(1); - expect(queriesMock.getTextLanguages).toHaveBeenCalledWith(org, app); + expect(getTextLanguages).toHaveBeenCalledTimes(1); + expect(getTextLanguages).toHaveBeenCalledWith(org, app); expect(queriesMock.getTextResources).toHaveBeenCalledTimes(textLanguagesMock.length); textLanguagesMock.forEach((language) => { expect(queriesMock.getTextResources).toHaveBeenCalledWith(org, app, language); diff --git a/frontend/packages/shared/src/mocks/mocks.ts b/frontend/packages/shared/src/mocks/mocks.ts new file mode 100644 index 00000000000..0f47fa51664 --- /dev/null +++ b/frontend/packages/shared/src/mocks/mocks.ts @@ -0,0 +1,234 @@ +import { + AppDeploymentsResponse, + AppReleasesResponse, + CreateRepoCommitPayload, + DatamodelMetadataResponse, + SearchRepositoryResponse, +} from 'app-shared/types/api'; +import { LayoutSets } from 'app-shared/types/api/LayoutSetsResponse'; +import { NewsList } from 'app-shared/types/api/NewsList'; +import { BranchStatus } from 'app-shared/types/BranchStatus'; +import { Commit } from 'app-shared/types/Commit'; +import { OrgsState } from 'app-shared/types/OrgsState'; +import { RepoStatus } from 'app-shared/types/RepoStatus'; +import { RuleConfig } from 'app-shared/types/RuleConfig'; +import { IRepository, ITextResourcesWithLanguage } from 'app-shared/types/global'; +import { User } from 'app-shared/types/User'; +import { AppConfig } from 'app-shared/types/AppConfig'; +import { Policy } from '@altinn/policy-editor'; +import { ApplicationMetadata } from 'app-shared/types/ApplicationMetadata'; +import { Resource, ResourceVersionStatus, Validation } from 'app-shared/types/ResourceAdm'; +import { AppLibVersion } from 'app-shared/types/AppLibVersion'; +import { BuildResult, BuildStatus } from 'app-shared/types/Build'; +import { AppDeployment } from 'app-shared/types/AppDeployment'; +import { DeployEnvironment } from 'app-shared/types/DeployEnvironment'; +import { Organization } from 'app-shared/types/Organization'; +import { Repository } from 'app-shared/types/Repository'; + +export const appReleasesResponse: AppReleasesResponse = { + results: [], +}; + +export const branchStatus: BranchStatus = { + commit: { + author: '', + committer: '', + id: '', + }, + name: '', +}; + +export const datamodelMetadataResponse: DatamodelMetadataResponse = { + elements: {}, +}; + +export const appDeploymentsResponse: AppDeploymentsResponse = { + results: [], +}; + +export const appDeployment: AppDeployment = { + id: '', + tagName: '', + app: '', + org: '', + envName: '', + deployedInEnv: false, + createdBy: '', + created: '', + build: { + id: '', + status: BuildStatus.completed, + result: BuildResult.succeeded, + started: '', + finished: '', + }, +}; + +export const deployEnvironment: DeployEnvironment = { + appsUrl: '', + platformUrl: '', + hostname: '', + appPrefix: '', + platformPrefix: '', + name: '', + type: '', +}; + +export const layoutSets: LayoutSets = { + sets: [], +}; + +export const newsList: NewsList = { + news: [], +}; + +export const orgsState: OrgsState = { + orgs: {}, +}; + +export const commit: Commit = { + message: '', + author: { name: '', email: '', when: new Date() }, + comitter: { name: '', email: '', when: new Date() }, + sha: '', + messageShort: '', + encoding: '', +}; + +export const repoStatus: RepoStatus = { + aheadBy: 0, + behindBy: 0, + contentStatus: [], + hasMergeConflict: false, + repositoryStatus: '', +}; + +export const ruleConfig: RuleConfig = { + data: { + ruleConnection: {}, + conditionalRendering: {}, + }, +}; + +export const textResourcesWithLanguage: ITextResourcesWithLanguage = { + language: '', + resources: [], +}; + +export const user: User = { + avatar_url: '', + email: '', + full_name: '', + id: 1, + login: '', +}; + +export const searchRepositoryResponse: SearchRepositoryResponse = { + data: [], + ok: false, + totalCount: 0, + totalPages: 0, +}; + +export const appConfig: AppConfig = { + repositoryName: '', + serviceName: '', + serviceId: '', + serviceDescription: '', +}; + +export const policy: Policy = { + rules: [], + requiredAuthenticationLevelEndUser: '0', + requiredAuthenticationLevelOrg: '', +}; + +export const applicationMetadata: ApplicationMetadata = { + id: '', + org: '', +}; + +export const resourceVersionStatus: ResourceVersionStatus = { + publishedVersions: [], +}; + +export const validation: Validation = { + status: 200, + errors: [], +}; + +export const appLibVersion: AppLibVersion = { + version: '', +}; + +export const customRepository: IRepository = { + name: '', + full_name: '', + owner: { + avatar_url: '', + login: '', + full_name: '', + }, + description: '', + is_cloned_to_local: false, + updated_at: '', + html_url: '', + clone_url: '', + id: 1, + user_has_starred: false, +}; + +export const repository: Repository = { + clone_url: '', + created_at: '', + default_branch: '', + description: '', + empty: false, + fork: false, + forks_count: 0, + full_name: '', + html_url: '', + id: 0, + is_cloned_to_local: false, + mirror: false, + name: '', + open_issues_count: 0, + owner: { + avatar_url: '', + email: '', + full_name: '', + id: 0, + login: '', + UserType: 0, + }, + permissions: { + admin: false, + pull: false, + push: false, + }, + private: false, + repositoryCreatedStatus: 0, + size: 0, + ssh_url: '', + stars_count: 0, + updated_at: '', + watchers_count: 0, + website: '', +}; + +export const createRepoCommitPayload: CreateRepoCommitPayload = { + message: '', + org: '', + repository: '', +}; + +export const organization: Organization = { + avatar_url: '', + id: 1, + username: '', +}; + +export const resource: Resource = { + identifier: '', + title: {}, +}; diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts index d10580e47e8..b7f0ebd3e72 100644 --- a/frontend/packages/shared/src/mocks/queriesMock.ts +++ b/frontend/packages/shared/src/mocks/queriesMock.ts @@ -1,92 +1,203 @@ import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; +import { Altinn2LinkService } from 'app-shared/types/Altinn2LinkService'; +import { AppConfig } from 'app-shared/types/AppConfig'; +import { AppLibVersion } from 'app-shared/types/AppLibVersion'; +import { ApplicationMetadata } from 'app-shared/types/ApplicationMetadata'; +import { BranchStatus } from 'app-shared/types/BranchStatus'; +import { Commit } from 'app-shared/types/Commit'; +import { DatamodelMetadataJson, DatamodelMetadataXsd } from 'app-shared/types/DatamodelMetadata'; +import { DeployEnvironment } from 'app-shared/types/DeployEnvironment'; +import { JsonSchema } from 'app-shared/types/JsonSchema'; +import { Organization } from 'app-shared/types/Organization'; +import { OrgsState } from 'app-shared/types/OrgsState'; +import { RepoStatus } from 'app-shared/types/RepoStatus'; +import { Repository } from 'app-shared/types/Repository'; +import { + Resource, + ResourceListItem, + ResourceVersionStatus, + Validation, +} from 'app-shared/types/ResourceAdm'; +import { RuleConfig } from 'app-shared/types/RuleConfig'; +import { User } from 'app-shared/types/User'; +import { + AppDeploymentsResponse, + AppReleasesResponse, + CreateRepoCommitPayload, + DatamodelMetadataResponse, + FormLayoutsResponse, + SearchRepositoryResponse, +} from 'app-shared/types/api'; +import { LayoutSets } from 'app-shared/types/api/LayoutSetsResponse'; +import { NewsList } from 'app-shared/types/api/NewsList'; +import { + IFrontEndSettings, + ILayoutSettings, + IRepository, + ITextResourcesObjectFormat, + ITextResourcesWithLanguage, +} from 'app-shared/types/global'; +import { WidgetSettingsResponse } from 'app-shared/types/widgetTypes'; +import { Policy, PolicyAction, PolicySubject } from 'packages/policy-editor'; +import { + appConfig, + appDeploymentsResponse, + appLibVersion, + appReleasesResponse, + applicationMetadata, + branchStatus, + commit, + createRepoCommitPayload, + datamodelMetadataResponse, + customRepository, + layoutSets, + newsList, + orgsState, + policy, + repoStatus, + repository, + resource, + resourceVersionStatus, + ruleConfig, + searchRepositoryResponse, + textResourcesWithLanguage, + user, + validation, +} from './mocks'; + export const queriesMock: ServicesContextProps = { - addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - addLanguageCode: jest.fn().mockImplementation(() => Promise.resolve({})), - addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), - addRepo: jest.fn().mockImplementation(() => Promise.resolve({})), - addXsdFromRepo: jest.fn().mockImplementation(() => Promise.resolve({})), - commitAndPushChanges: jest.fn().mockImplementation(() => Promise.resolve({})), - configureLayoutSet: jest.fn().mockImplementation(() => Promise.resolve({})), - copyApp: jest.fn().mockImplementation(() => Promise.resolve({})), - createDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), - createDeployment: jest.fn().mockImplementation(() => Promise.resolve({})), - createRelease: jest.fn().mockImplementation(() => Promise.resolve({})), - createRepoCommit: jest.fn().mockImplementation(() => Promise.resolve({})), - createResource: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), - deleteLanguageCode: jest.fn().mockImplementation(() => Promise.resolve({})), - generateModels: jest.fn().mockImplementation(() => Promise.resolve({})), - getAppReleases: jest.fn().mockImplementation(() => Promise.resolve({})), - getBranchStatus: jest.fn().mockImplementation(() => Promise.resolve({})), - getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve([])), - getComponentsCommonDefsSchema: jest.fn().mockImplementation(() => Promise.resolve([])), - getDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), - getDatamodelMetadata: jest.fn().mockImplementation(() => Promise.resolve({ elements: {} })), - getDatamodelsJson: jest.fn().mockImplementation(() => Promise.resolve([])), - getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve([])), - getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve([])), - getDeployments: jest.fn().mockImplementation(() => Promise.resolve({})), - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), - getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve([])), - getFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve({})), - getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve({})), - getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve([])), - getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve({})), - getNewsList: jest.fn().mockImplementation(() => Promise.resolve({})), - getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve([])), - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve([])), - getOrgList: jest.fn().mockImplementation(() => Promise.resolve({})), - getOrganizations: jest.fn().mockImplementation(() => Promise.resolve([])), - getPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - getPolicyActions: jest.fn().mockImplementation(() => Promise.resolve([])), - getPolicySubjects: jest.fn().mockImplementation(() => Promise.resolve([])), - getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(null)), - getRepoPull: jest.fn().mockImplementation(() => Promise.resolve({})), - getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve({})), - getResource: jest.fn().mockImplementation(() => Promise.resolve({})), - getResourceList: jest.fn().mockImplementation(() => Promise.resolve([])), - getResourcePublishStatus: jest.fn().mockImplementation(() => Promise.resolve({})), - getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve({})), - getRuleModel: jest.fn().mockImplementation(() => Promise.resolve({})), - getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve([])), - getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve([])), - getTextResources: jest.fn().mockImplementation(() => Promise.resolve({})), - getUser: jest.fn().mockImplementation(() => Promise.resolve({})), - getValidatePolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - getValidateResource: jest.fn().mockImplementation(() => Promise.resolve({})), - getWidgetSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - logout: jest.fn().mockImplementation(() => Promise.resolve({})), - pushRepoChanges: jest.fn().mockImplementation(() => Promise.resolve({})), - resetRepoChanges: jest.fn().mockImplementation(() => Promise.resolve({})), - saveDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), - saveFormLayout: jest.fn().mockImplementation(() => Promise.resolve({})), - saveFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), - saveRuleConfig: jest.fn().mockImplementation(() => Promise.resolve({})), - searchRepos: jest.fn().mockImplementation(() => Promise.resolve({})), - setStarredRepo: jest.fn().mockImplementation(() => Promise.resolve({})), - unsetStarredRepo: jest.fn().mockImplementation(() => Promise.resolve({})), - updateAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - updateFormLayoutName: jest.fn().mockImplementation(() => Promise.resolve({})), - updatePolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - updateResource: jest.fn().mockImplementation(() => Promise.resolve({})), - updateTextId: jest.fn().mockImplementation(() => Promise.resolve({})), - updateTranslationByLangCode: jest.fn().mockImplementation(() => Promise.resolve({})), - upsertTextResources: jest.fn().mockImplementation(() => Promise.resolve({})), - getBpmnFile: jest.fn().mockImplementation(() => Promise.resolve({})), - updateBpmnXml: jest.fn().mockImplementation(() => Promise.resolve({})), - getAppPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - updateAppPolicy: jest.fn().mockImplementation(() => Promise.resolve({})), - getAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), - getAppMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - updateAppMetadata: jest.fn().mockImplementation(() => Promise.resolve({})), - updateAppConfig: jest.fn().mockImplementation(() => Promise.resolve({})), - getRepoInitialCommit: jest.fn().mockImplementation(() => Promise.resolve({})), - publishResource: jest.fn().mockImplementation(() => Promise.resolve({})), - getAltinn2LinkServices: jest.fn().mockImplementation(() => Promise.resolve([])), - importResourceFromAltinn2: jest.fn().mockImplementation(() => Promise.resolve({})), - getAppLibVersion: jest.fn().mockImplementation(() => Promise.resolve({})), + // Queries + getAppReleases: jest + .fn() + .mockImplementation(() => Promise.resolve(appReleasesResponse)), + getBranchStatus: jest.fn().mockImplementation(() => Promise.resolve(branchStatus)), + getComponentSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getComponentsCommonDefsSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + getDatamodelMetadata: jest + .fn() + .mockImplementation(() => + Promise.resolve(datamodelMetadataResponse), + ), + getDatamodelsJson: jest + .fn() + .mockImplementation(() => Promise.resolve([])), + getDatamodelsXsd: jest.fn().mockImplementation(() => Promise.resolve([])), + getDeployPermissions: jest.fn().mockImplementation(() => Promise.resolve([])), + getDeployments: jest + .fn() + .mockImplementation(() => Promise.resolve(appDeploymentsResponse)), + getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), + getExpressionSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + getFormLayouts: jest.fn().mockImplementation(() => Promise.resolve({})), + getFrontEndSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('')), + getLayoutSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getLayoutSets: jest.fn().mockImplementation(() => Promise.resolve(layoutSets)), + getNewsList: jest.fn().mockImplementation(() => Promise.resolve(newsList)), + getNumberFormatSchema: jest.fn().mockImplementation(() => Promise.resolve([])), + getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve([])), + getOrgList: jest.fn().mockImplementation(() => Promise.resolve(orgsState)), + getOrganizations: jest.fn().mockImplementation(() => Promise.resolve([])), + getRepoInitialCommit: jest.fn().mockImplementation(() => Promise.resolve(commit)), + getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(repository)), + getRepoPull: jest.fn().mockImplementation(() => Promise.resolve(repoStatus)), + getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve(repoStatus)), + getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfig)), + getRuleModel: jest.fn().mockImplementation(() => Promise.resolve('')), + getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve([])), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve([])), + getTextResources: jest + .fn() + .mockImplementation(() => + Promise.resolve(textResourcesWithLanguage), + ), + getUser: jest.fn().mockImplementation(() => Promise.resolve(user)), + getWidgetSettings: jest + .fn() + .mockImplementation(() => Promise.resolve({})), + searchRepos: jest + .fn() + .mockImplementation(() => Promise.resolve(searchRepositoryResponse)), + + // Queries - Settings modal + getAppConfig: jest.fn().mockImplementation(() => Promise.resolve(appConfig)), + getAppPolicy: jest.fn().mockImplementation(() => Promise.resolve(policy)), + getAppMetadata: jest + .fn() + .mockImplementation(() => Promise.resolve(applicationMetadata)), + + // Queries - Resourceadm + getAltinn2LinkServices: jest + .fn() + .mockImplementation(() => Promise.resolve([])), + getPolicyActions: jest.fn().mockImplementation(() => Promise.resolve([])), + getPolicy: jest.fn().mockImplementation(() => Promise.resolve(policy)), + getPolicySubjects: jest.fn().mockImplementation(() => Promise.resolve([])), + getResource: jest.fn().mockImplementation(() => Promise.resolve(resource)), + getResourceList: jest.fn().mockImplementation(() => Promise.resolve([])), + getResourcePublishStatus: jest + .fn() + .mockImplementation(() => Promise.resolve(resourceVersionStatus)), + getValidatePolicy: jest.fn().mockImplementation(() => Promise.resolve(validation)), + getValidateResource: jest.fn().mockImplementation(() => Promise.resolve(validation)), + + // Queries - PrgetBpmnFile + getAppLibVersion: jest + .fn() + .mockImplementation(() => Promise.resolve(appLibVersion)), + getBpmnFile: jest.fn().mockImplementation(() => Promise.resolve('')), + + // Mutations + addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve()), + addLanguageCode: jest.fn().mockImplementation(() => Promise.resolve()), + addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve()), + addRepo: jest.fn().mockImplementation(() => Promise.resolve(customRepository)), + addXsdFromRepo: jest.fn().mockImplementation(() => Promise.resolve({})), + commitAndPushChanges: jest + .fn() + .mockImplementation(() => Promise.resolve(createRepoCommitPayload)), + configureLayoutSet: jest.fn().mockImplementation(() => Promise.resolve(layoutSets)), + copyApp: jest.fn().mockImplementation(() => Promise.resolve()), + createDatamodel: jest.fn().mockImplementation(() => Promise.resolve({})), + createDeployment: jest.fn().mockImplementation(() => Promise.resolve()), + createRelease: jest.fn().mockImplementation(() => Promise.resolve()), + createRepoCommit: jest + .fn() + .mockImplementation(() => Promise.resolve(createRepoCommitPayload)), + deleteAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve()), + deleteDatamodel: jest.fn().mockImplementation(() => Promise.resolve()), + deleteFormLayout: jest.fn().mockImplementation(() => Promise.resolve()), + deleteLanguageCode: jest.fn().mockImplementation(() => Promise.resolve()), + generateModels: jest.fn().mockImplementation(() => Promise.resolve()), + logout: jest.fn().mockImplementation(() => Promise.resolve()), + pushRepoChanges: jest.fn().mockImplementation(() => Promise.resolve()), + resetRepoChanges: jest.fn().mockImplementation(() => Promise.resolve()), + saveDatamodel: jest.fn().mockImplementation(() => Promise.resolve()), + saveFormLayout: jest.fn().mockImplementation(() => Promise.resolve()), + saveFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), + saveRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfig)), + setStarredRepo: jest.fn().mockImplementation(() => Promise.resolve([])), + unsetStarredRepo: jest.fn().mockImplementation(() => Promise.resolve()), + updateAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve()), + updateFormLayoutName: jest.fn().mockImplementation(() => Promise.resolve()), + updateTextId: jest.fn().mockImplementation(() => Promise.resolve()), + updateTranslationByLangCode: jest.fn().mockImplementation(() => Promise.resolve()), + updateAppPolicy: jest.fn().mockImplementation(() => Promise.resolve()), + updateAppMetadata: jest.fn().mockImplementation(() => Promise.resolve()), + updateAppConfig: jest.fn().mockImplementation(() => Promise.resolve()), + upsertTextResources: jest + .fn() + .mockImplementation(() => Promise.resolve({})), + + // Mutations - Resourceadm + createResource: jest.fn().mockImplementation(() => Promise.resolve()), + importResourceFromAltinn2: jest.fn().mockImplementation(() => Promise.resolve(null)), + publishResource: jest.fn().mockImplementation(() => Promise.resolve()), + updatePolicy: jest.fn().mockImplementation(() => Promise.resolve()), + updateResource: jest.fn().mockImplementation(() => Promise.resolve()), + + // Mutations - ProcessEditor + updateBpmnXml: jest.fn().mockImplementation(() => Promise.resolve()), }; diff --git a/frontend/packages/shared/src/types/AppLibVersion.ts b/frontend/packages/shared/src/types/AppLibVersion.ts new file mode 100644 index 00000000000..41755d1e97a --- /dev/null +++ b/frontend/packages/shared/src/types/AppLibVersion.ts @@ -0,0 +1,3 @@ +export interface AppLibVersion { + version: string; +} diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index c7e7bafb327..37aa8b1160a 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -15,7 +15,6 @@ import { useTextResourcesQuery } from 'app-shared/hooks/queries/useTextResources import { DEFAULT_LANGUAGE } from 'app-shared/constants'; import { typedLocalStorage } from 'app-shared/utils/webStorage'; import { addFeatureFlagToLocalStorage } from 'app-shared/utils/featureToggleUtils'; -import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; const user = userEvent.setup(); diff --git a/frontend/packages/ux-editor/src/components/config/EditFormComponent.test.tsx b/frontend/packages/ux-editor/src/components/config/EditFormComponent.test.tsx index bf828b9e6d1..1de7a6c4fb0 100644 --- a/frontend/packages/ux-editor/src/components/config/EditFormComponent.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/EditFormComponent.test.tsx @@ -8,6 +8,7 @@ import { useLayoutSchemaQuery } from '../../hooks/queries/useLayoutSchemaQuery'; import { mockUseTranslation } from '../../../../../testing/mocks/i18nMock'; import { ComponentType } from 'app-shared/types/ComponentType'; import { useDatamodelMetadataQuery } from '../../hooks/queries/useDatamodelMetadataQuery'; +import { DatamodelMetadataResponse } from 'app-shared/types/api'; const user = userEvent.setup(); @@ -37,7 +38,7 @@ jest.mock('./componentSpecificContent/Image/ImageComponent', () => ({ })); const getDatamodelMetadata = () => - Promise.resolve({ + Promise.resolve({ elements: { testModel: { id: 'testModel', diff --git a/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx b/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx index e8a3e120b2a..6cafdfa8438 100644 --- a/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/EditFormContainer.test.tsx @@ -13,6 +13,8 @@ import { import { useLayoutSchemaQuery } from '../../hooks/queries/useLayoutSchemaQuery'; import { container1IdMock, externalLayoutsMock, layoutMock } from '../../testing/layoutMock'; import { textMock } from '../../../../../testing/mocks/i18nMock'; +import { FormLayoutsResponse } from 'app-shared/types/api'; +import { ILayoutSettings } from 'app-shared/types/global'; const user = userEvent.setup(); @@ -84,10 +86,12 @@ describe('EditFormContainer', () => { }); const waitForData = async () => { - const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayouts = jest + .fn() + .mockImplementation(() => Promise.resolve(externalLayoutsMock)); const getFormLayoutSettings = jest .fn() - .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); const formLayoutsResult = renderHookWithMockStore( {}, { getFormLayouts }, diff --git a/frontend/packages/ux-editor/src/components/config/SelectDataModelComponent.test.tsx b/frontend/packages/ux-editor/src/components/config/SelectDataModelComponent.test.tsx index 48964a9383f..9a36b57fa03 100644 --- a/frontend/packages/ux-editor/src/components/config/SelectDataModelComponent.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/SelectDataModelComponent.test.tsx @@ -8,9 +8,10 @@ import { SelectDataModelComponent } from './SelectDataModelComponent'; import { textMock } from '../../../../../testing/mocks/i18nMock'; import { useDatamodelMetadataQuery } from '../../hooks/queries/useDatamodelMetadataQuery'; import userEvent from '@testing-library/user-event'; +import { DatamodelMetadataResponse } from 'app-shared/types/api'; const getDatamodelMetadata = () => - Promise.resolve({ + Promise.resolve({ elements: { testModel: { id: 'testModel', diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx index a2bde6e1128..8c5ac3e7b19 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditCodeList.test.tsx @@ -13,7 +13,9 @@ describe('EditCodeList', () => { it('should render the component', async () => { await render({ queries: { - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + getOptionListIds: jest + .fn() + .mockImplementation(() => Promise.resolve(optionListIdsMock)), }, }); expect(await screen.findByText('Bytt til egendefinert kodeliste')).toBeInTheDocument(); @@ -22,7 +24,9 @@ describe('EditCodeList', () => { it('should render the component when optionListIds is undefined', async () => { await render({ queries: { - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + getOptionListIds: jest + .fn() + .mockImplementation(() => Promise.resolve(optionListIdsMock)), }, }); diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx index af1a016b002..980a32edfbb 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { screen, waitFor, within } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { renderWithMockStore } from '../../../testing/mocks'; import { appDataMock, textResourcesMock } from '../../../testing/stateMocks'; import { IAppDataState } from '../../../features/appData/appDataReducers'; diff --git a/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx b/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx index fcd21ce1ae8..dece3900eb4 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx +++ b/frontend/packages/ux-editor/src/containers/FormDesigner.test.tsx @@ -19,8 +19,8 @@ const render = () => { getFormLayoutSettings: jest .fn() .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)), - getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), - getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('test')), + getRuleModel: jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)), + getInstanceIdForPreview: jest.fn().mockImplementation(() => Promise.resolve('test')), }; const props = { selectedLayout: 'test-layout', diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts index 5ebf18d5459..36663c7aef1 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddLayoutMutation.test.ts @@ -6,6 +6,8 @@ import { waitFor } from '@testing-library/react'; import { useFormLayoutSettingsQuery } from '../queries/useFormLayoutSettingsQuery'; import { ComponentType } from 'app-shared/types/ComponentType'; import { externalLayoutsMock } from '../../testing/layoutMock'; +import { FormLayoutsResponse } from 'app-shared/types/api'; +import { ILayoutSettings } from 'app-shared/types/global'; // Test data: const org = 'org'; @@ -74,10 +76,12 @@ describe('useAddLayoutMutation', () => { }); const renderAndWaitForData = async () => { - const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayouts = jest + .fn() + .mockImplementation(() => Promise.resolve(externalLayoutsMock)); const getFormLayoutSettings = jest .fn() - .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); + .mockImplementation(() => Promise.resolve(formLayoutSettingsMock)); const formLayoutsResult = renderHookWithMockStore( {}, { getFormLayouts }, diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts index d56ab5210ac..c21bdfc27f0 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteFormContainerMutation.test.ts @@ -4,6 +4,7 @@ import { waitFor } from '@testing-library/react'; import { useFormLayoutsQuery } from '../queries/useFormLayoutsQuery'; import { useDeleteFormContainerMutation } from './useDeleteFormContainerMutation'; import { container1IdMock, externalLayoutsMock, layout1NameMock } from '../../testing/layoutMock'; +import { FormLayoutsResponse } from 'app-shared/types/api'; // Test data: const org = 'org'; @@ -31,7 +32,9 @@ describe('useDeleteFormContainerMutation', () => { }); const renderDeleteFormContainerMutation = async () => { - const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayouts = jest + .fn() + .mockImplementation(() => Promise.resolve(externalLayoutsMock)); const formLayoutsResult = renderHookWithMockStore( {}, { getFormLayouts }, diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts index 302c2eb085b..8687ea713bf 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentOrderMutation.test.ts @@ -12,6 +12,7 @@ import { layout1NameMock, layoutMock, } from '../../testing/layoutMock'; +import { FormLayoutsResponse } from 'app-shared/types/api'; // Test data: const org = 'org'; @@ -54,7 +55,9 @@ describe('useUpdateFormComponentOrderMutation', () => { }); const renderAndWaitForData = async () => { - const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getFormLayouts = jest + .fn() + .mockImplementation(() => Promise.resolve(externalLayoutsMock)); const formLayoutsResult = renderHookWithMockStore( {}, { getFormLayouts }, diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts index cf89761eb3c..079c628edb6 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormContainerMutation.test.ts @@ -15,6 +15,8 @@ import { layout1NameMock, } from '../../testing/layoutMock'; import { ruleConfig as ruleConfigMock } from '../../testing/ruleConfigMock'; +import { FormLayoutsResponse } from 'app-shared/types/api'; +import { RuleConfig } from 'app-shared/types/RuleConfig'; // Test data: const org = 'org'; @@ -62,8 +64,12 @@ describe('useUpdateFormContainerMutation', () => { }); const renderAndWaitForData = async () => { - const getFormLayouts = jest.fn().mockImplementation(() => Promise.resolve(externalLayoutsMock)); - const getRuleConfig = jest.fn().mockImplementation(() => Promise.resolve(ruleConfigMock)); + const getFormLayouts = jest + .fn() + .mockImplementation(() => Promise.resolve(externalLayoutsMock)); + const getRuleConfig = jest + .fn() + .mockImplementation(() => Promise.resolve(ruleConfigMock)); const formLayoutsResult = renderHookWithMockStore( {}, { getFormLayouts }, diff --git a/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts b/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts index 7b03aa6d974..e7b19469de9 100644 --- a/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts +++ b/frontend/packages/ux-editor/src/hooks/queries/useRuleModelQuery.test.ts @@ -1,8 +1,7 @@ -import { queriesMock } from 'app-shared/mocks/queriesMock'; import { renderHookWithMockStore } from '../../testing/mocks'; import { waitFor } from '@testing-library/react'; import { useRuleModelQuery } from './useRuleModelQuery'; -import { +import ruleHandlerMock, { condition1Input1Label, condition1Input1Name, condition1Name, @@ -23,17 +22,20 @@ import { rule2Input2Name, rule2Name, } from '../../testing/ruleHandlerMock'; +import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; // Test data: const org = 'org'; const app = 'app'; const selectedLayoutSet = 'test-layout-set'; +const getRuleModel = jest.fn().mockImplementation(() => Promise.resolve(ruleHandlerMock)); + describe('useRuleModelQuery', () => { it('Calls getRuleModel with correct parameters', async () => { await renderAndWaitForSuccess(); - expect(queriesMock.getRuleModel).toHaveBeenCalledTimes(1); - expect(queriesMock.getRuleModel).toHaveBeenCalledWith(org, app, selectedLayoutSet); + expect(getRuleModel).toHaveBeenCalledTimes(1); + expect(getRuleModel).toHaveBeenCalledWith(org, app, selectedLayoutSet); }); it('Parses file correctly and returns an array of rules and conditions', async () => { @@ -74,10 +76,11 @@ describe('useRuleModelQuery', () => { }); }); -const renderAndWaitForSuccess = async () => { - const { renderHookResult } = renderHookWithMockStore()(() => - useRuleModelQuery(org, app, selectedLayoutSet), - ); +const renderAndWaitForSuccess = async (queries: Partial = {}) => { + const { renderHookResult } = renderHookWithMockStore( + {}, + { getRuleModel }, + )(() => useRuleModelQuery(org, app, selectedLayoutSet)); await waitFor(() => expect(renderHookResult.result.current.isSuccess).toBe(true)); return renderHookResult; }; diff --git a/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts b/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts index bd8b462cf31..378f5d0b256 100644 --- a/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts +++ b/frontend/packages/ux-editor/src/hooks/useValidateComponent.test.ts @@ -145,7 +145,9 @@ describe('useValidateComponent', () => { const render = (component: FormComponent) => { const queries = { - getOptionListIds: jest.fn().mockImplementation(() => Promise.resolve(optionListIdsMock)), + getOptionListIds: jest + .fn() + .mockImplementation(() => Promise.resolve(optionListIdsMock)), }; return renderHookWithMockStore({}, queries)(() => useValidateComponent(component)) .renderHookResult.result.current; diff --git a/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx b/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx index 336e0e92b8b..9d86a43c5ba 100644 --- a/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx +++ b/frontend/resourceadm/components/ImportResourceModal/ServiceContent/ServiceContent.test.tsx @@ -12,12 +12,11 @@ import userEvent from '@testing-library/user-event'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const mockSelectedContext: string = 'selectedContext'; const mockEnv: string = 'env1'; -const getAltinn2LinkServices = jest.fn().mockImplementation(() => Promise.resolve({})); - const mockAltinn2LinkService: Altinn2LinkService = { externalServiceCode: 'code1', externalServiceEditionCode: 'edition1', @@ -47,7 +46,7 @@ describe('ServiceContent', () => { it('fetches getAltinn2LinkServices on mount', () => { render(); - expect(getAltinn2LinkServices).toHaveBeenCalledTimes(1); + expect(queriesMock.getAltinn2LinkServices).toHaveBeenCalledTimes(1); }); it('shows an error message if an error occured on the "getAltinn2LinkServices" query', async () => { @@ -69,12 +68,7 @@ describe('ServiceContent', () => { }); it('renders empty list state correctly', async () => { - render( - {}, - { - getAltinn2LinkServices: () => Promise.resolve([]), - }, - ); + render(); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.import_resource_spinner')), @@ -115,9 +109,11 @@ describe('ServiceContent', () => { }); const resolveAndWaitForSpinnerToDisappear = async (props: Partial = {}) => { - getAltinn2LinkServices.mockImplementation(() => Promise.resolve(mockAltinn2LinkServices)); + const getAltinn2LinkServices = jest + .fn() + .mockImplementation(() => Promise.resolve(mockAltinn2LinkServices)); - render(props); + render(props, { getAltinn2LinkServices }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.import_resource_spinner')), ); @@ -129,7 +125,7 @@ const render = ( queryClient: QueryClient = createQueryClientMock(), ) => { const allQueries: ServicesContextProps = { - getAltinn2LinkServices, + ...queriesMock, ...queries, }; diff --git a/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx b/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx index b235bf82ab0..977585a3e1d 100644 --- a/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx +++ b/frontend/resourceadm/pages/DeployResourcePage/DeployResourcePage.test.tsx @@ -13,21 +13,14 @@ import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contex import { QueryClient, UseMutationResult } from '@tanstack/react-query'; import { usePublishResourceMutation } from 'resourceadm/hooks/mutations'; import { RepoStatus } from 'app-shared/types/RepoStatus'; -import { ResourceVersionStatus, Version, Validation } from 'app-shared/types/ResourceAdm'; +import { Validation } from 'app-shared/types/ResourceAdm'; import userEvent from '@testing-library/user-event'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const mockResourceId: string = 'r1'; const mockSelectedContext: string = 'test'; const mockId: string = 'page-content-deploy'; -const mockRepoStatus: RepoStatus = { - aheadBy: 0, - behindBy: 0, - contentStatus: [], - hasMergeConflict: false, - repositoryStatus: 'Ok', -}; - const mockRepoStatusAhead: RepoStatus = { aheadBy: 1, behindBy: 0, @@ -36,18 +29,6 @@ const mockRepoStatusAhead: RepoStatus = { repositoryStatus: 'Ok', }; -const mockVersionTT02: Version = { version: null, environment: 'tt02' }; -const mockVersionPROD: Version = { version: null, environment: 'prod' }; -const mockVersionAT22: Version = { version: null, environment: 'at22' }; -const mockVersionAT23: Version = { version: null, environment: 'at23' }; - -const mockPublishStatus: ResourceVersionStatus = { - policyVersion: null, - resourceVersion: '1', - publishedVersions: [mockVersionTT02, mockVersionPROD, mockVersionAT22, mockVersionAT23], -}; - -const mockValidatePolicyData1: Validation = { status: 200, errors: [] }; const mockValidatePolicyData2: Validation = { status: 400, errors: ['rule1.policyerror.missingsubject'], @@ -57,18 +38,12 @@ const mockValidatePolicyData3: Validation = { errors: ['policyerror.missingpolicy'], }; -const mockValidateResourceData1: Validation = { status: 200, errors: [] }; const mockValidateResourceData2: Validation = { status: 400, errors: ['resource.title'] }; const mockResourceVersionText: string = '2'; const mockNavigateToPageWithError = jest.fn(); const mockOnSaveVersion = jest.fn(); -const getRepoStatus = jest.fn().mockImplementation(() => Promise.resolve({})); -const getResourcePublishStatus = jest.fn().mockImplementation(() => Promise.resolve({})); -const getValidatePolicy = jest.fn().mockImplementation(() => Promise.resolve({})); -const getValidateResource = jest.fn().mockImplementation(() => Promise.resolve({})); - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ @@ -104,22 +79,22 @@ describe('DeployResourcePage', () => { it('fetches repo status data on mount', () => { render(); - expect(getRepoStatus).toHaveBeenCalledTimes(1); + expect(queriesMock.getRepoStatus).toHaveBeenCalledTimes(1); }); it('fetches resource publish status data on mount', () => { render(); - expect(getResourcePublishStatus).toHaveBeenCalledTimes(1); + expect(queriesMock.getResourcePublishStatus).toHaveBeenCalledTimes(1); }); it('fetches validates policy on mount', () => { render(); - expect(getValidatePolicy).toHaveBeenCalledTimes(1); + expect(queriesMock.getValidatePolicy).toHaveBeenCalledTimes(1); }); it('fetches validates resource on mount', () => { render(); - expect(getValidateResource).toHaveBeenCalledTimes(1); + expect(queriesMock.getValidateResource).toHaveBeenCalledTimes(1); }); it.each(['getResourcePublishStatus', 'getValidatePolicy', 'getValidateResource'])( @@ -301,7 +276,7 @@ describe('DeployResourcePage', () => { it('disables the deploy buttons when there is validate resource error', async () => { await resolveAndWaitForSpinnerToDisappear({ - getValidateResource: () => Promise.resolve(mockValidateResourceData2), + getValidateResource: () => Promise.resolve(mockValidateResourceData2), }); const tt02 = textMock('resourceadm.deploy_test_env'); @@ -320,7 +295,7 @@ describe('DeployResourcePage', () => { it('disables the deploy buttons when there is validate policy error', async () => { await resolveAndWaitForSpinnerToDisappear({ - getValidatePolicy: () => Promise.resolve(mockValidatePolicyData2), + getValidatePolicy: () => Promise.resolve(mockValidatePolicyData2), }); const tt02 = textMock('resourceadm.deploy_test_env'); const prod = textMock('resourceadm.deploy_prod_env'); @@ -392,12 +367,12 @@ const resolveAndWaitForSpinnerToDisappear = async ( queries: Partial = {}, props: Partial = {}, ) => { - getRepoStatus.mockImplementation(() => Promise.resolve(mockRepoStatus)); - getResourcePublishStatus.mockImplementation(() => Promise.resolve(mockPublishStatus)); - getValidatePolicy.mockImplementation(() => Promise.resolve(mockValidatePolicyData1)); - getValidateResource.mockImplementation(() => Promise.resolve(mockValidateResourceData1)); - - render(queries, props); + render( + { + ...queries, + }, + props, + ); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.deploy_spinner')), ); @@ -408,16 +383,12 @@ const render = ( props: Partial = {}, queryClient: QueryClient = createQueryClientMock(), ) => { - const allQueries: ServicesContextProps = { - getRepoStatus, - getResourcePublishStatus, - getValidatePolicy, - getValidateResource, + const allQueries = { ...queries, }; return rtlRender( - + , diff --git a/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx b/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx index 89aee9e80f7..e8aeede486b 100644 --- a/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx +++ b/frontend/resourceadm/pages/PolicyEditorPage/PolicyEditorPage.test.tsx @@ -88,21 +88,21 @@ describe('PolicyEditorPage', () => { screen.queryByRole('heading', { name: textMock('policy_editor.rules'), level: 2 }), ).not.toBeInTheDocument(); - getPolicy.mockImplementation(() => Promise.resolve(mockPolicy)); + getPolicy.mockImplementation(() => Promise.resolve(mockPolicy)); expect(screen.getByTitle(textMock('resourceadm.policy_editor_spinner'))).toBeInTheDocument(); expect( screen.queryByRole('heading', { name: textMock('policy_editor.rules'), level: 2 }), ).not.toBeInTheDocument(); - getPolicyActions.mockImplementation(() => Promise.resolve(mockActions)); + getPolicyActions.mockImplementation(() => Promise.resolve(mockActions)); expect(screen.getByTitle(textMock('resourceadm.policy_editor_spinner'))).toBeInTheDocument(); expect( screen.queryByRole('heading', { name: textMock('policy_editor.rules'), level: 2 }), ).not.toBeInTheDocument(); - getPolicySubjects.mockImplementation(() => Promise.resolve(mockSubjects)); + getPolicySubjects.mockImplementation(() => Promise.resolve(mockSubjects)); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.policy_editor_spinner')), diff --git a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx index 8f3783bdb64..d579b137761 100644 --- a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx +++ b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx @@ -9,6 +9,8 @@ import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { Organization } from 'app-shared/types/Organization'; const mockResourceListItem1: ResourceListItem = { title: { nb: 'resource 1', nn: '', en: '' }, @@ -53,9 +55,6 @@ const mockResourceList: ResourceListItem[] = [ mockResourceListItem5, ]; -const getResourceList = jest.fn().mockImplementation(() => Promise.resolve({})); -const getOrganizations = jest.fn().mockImplementation(() => Promise.resolve([])); - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ @@ -69,12 +68,12 @@ describe('ResourceDashBoardPage', () => { }); it('fetches resource list on mount', () => { render(); - expect(getResourceList).toHaveBeenCalledTimes(1); + expect(queriesMock.getResourceList).toHaveBeenCalledTimes(1); }); it('shows correct organization header', async () => { - getOrganizations.mockImplementation(() => - Promise.resolve([ + const getOrganizations = jest.fn().mockImplementation(() => + Promise.resolve([ { avatar_url: 'http://studio.localhost/repos/avatars/5d076e5c3d34cb8bb08e54a4bb7e223e', description: 'Internt organisasjon for test av løsning', @@ -86,7 +85,7 @@ describe('ResourceDashBoardPage', () => { }, ]), ); - render(); + render({ getOrganizations }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -110,8 +109,10 @@ describe('ResourceDashBoardPage', () => { }); it('does not show the spinner when the resource list is present', async () => { - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -127,8 +128,10 @@ describe('ResourceDashBoardPage', () => { it('opens the import resource from altinn 2 modal on click', async () => { const user = userEvent.setup(); - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -154,8 +157,10 @@ describe('ResourceDashBoardPage', () => { it('opens the create new resource modal on click', async () => { const user = userEvent.setup(); - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -181,8 +186,10 @@ describe('ResourceDashBoardPage', () => { it('filters the resource list when the search value changes', async () => { const user = userEvent.setup(); - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -198,8 +205,10 @@ describe('ResourceDashBoardPage', () => { }); it('does not display the error message when the list is not empty', async () => { - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -211,8 +220,10 @@ describe('ResourceDashBoardPage', () => { it('displays empty list message when the list is empty', async () => { const user = userEvent.setup(); - getResourceList.mockImplementation(() => Promise.resolve(mockResourceList)); - render(); + const getResourceList = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResourceList)); + render({ getResourceList }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.dashboard_spinner')), ); @@ -236,14 +247,9 @@ const render = ( queries: Partial = {}, queryClient: QueryClient = createQueryClientMock(), ) => { - const allQueries: ServicesContextProps = { - getResourceList, - getOrganizations, - ...queries, - }; return rtlRender( - + , diff --git a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx index fdd10d2891f..3f385048128 100644 --- a/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx +++ b/frontend/resourceadm/pages/ResourcePage/ResourcePage.test.tsx @@ -9,6 +9,7 @@ import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; import { MemoryRouter } from 'react-router-dom'; import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contexts/ServicesContext'; import { QueryClient } from '@tanstack/react-query'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const mockResource1: Resource = { identifier: 'r1', @@ -29,11 +30,6 @@ const mockResource2: Resource = { const mockSelectedContext: string = 'test'; -const getValidatePolicy = jest.fn().mockImplementation(() => Promise.resolve({})); -const getValidateResource = jest.fn().mockImplementation(() => Promise.resolve({})); -const getResource = jest.fn().mockImplementation(() => Promise.resolve({})); -const updateResource = jest.fn().mockImplementation(() => Promise.resolve({})); - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ @@ -50,17 +46,17 @@ describe('ResourcePage', () => { it('fetches validate policy on mount', () => { render(); - expect(getValidatePolicy).toHaveBeenCalledTimes(1); + expect(queriesMock.getValidatePolicy).toHaveBeenCalledTimes(1); }); it('fetches validate resource on mount', () => { render(); - expect(getValidateResource).toHaveBeenCalledTimes(1); + expect(queriesMock.getValidateResource).toHaveBeenCalledTimes(1); }); it('fetches resource on mount', () => { render(); - expect(getResource).toHaveBeenCalledTimes(1); + expect(queriesMock.getResource).toHaveBeenCalledTimes(1); }); it('displays left navigation bar on mount', () => { @@ -89,9 +85,11 @@ describe('ResourcePage', () => { }); it('displays migrate tab in left navigation bar when resource reference is present in resource', async () => { - getResource.mockImplementation(() => Promise.resolve(mockResource1)); + const getResource = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResource1)); - render(); + render({ getResource }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.about_resource_spinner')), ); @@ -102,9 +100,11 @@ describe('ResourcePage', () => { }); it('does not display migrate tab in left navigation bar when resource reference is not in resource', async () => { - getResource.mockImplementation(() => Promise.resolve(mockResource2)); + const getResource = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResource2)); - render(); + render({ getResource }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.about_resource_spinner')), ); @@ -116,9 +116,12 @@ describe('ResourcePage', () => { it('opens navigation modal when resource has errors', async () => { const user = userEvent.setup(); - getResource.mockImplementation(() => Promise.resolve(mockResource2)); + const getResource = jest + .fn() + .mockImplementation(() => Promise.resolve(mockResource2)); + const getValidateResource = jest.fn().mockImplementation(() => Promise.reject(null)); - render(); + render({ getResource, getValidateResource }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('resourceadm.about_resource_spinner')), ); @@ -148,16 +151,9 @@ const render = ( queries: Partial = {}, queryClient: QueryClient = createQueryClientMock(), ) => { - const allQueries: ServicesContextProps = { - getValidatePolicy, - getValidateResource, - getResource, - updateResource, - ...queries, - }; return rtlRender( - + , From 08e6af39d680b38f2aaea534ad252911de56b463 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 20 Dec 2023 17:23:06 +0100 Subject: [PATCH 07/15] Fix date formatting --- frontend/app-development/utils/dateUtils/dateUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/app-development/utils/dateUtils/dateUtils.ts b/frontend/app-development/utils/dateUtils/dateUtils.ts index 7ee9564a43a..17befef13b7 100644 --- a/frontend/app-development/utils/dateUtils/dateUtils.ts +++ b/frontend/app-development/utils/dateUtils/dateUtils.ts @@ -1,3 +1,7 @@ +export const isDateValid = (dateStr: string): boolean => { + return !isNaN(Date.parse(dateStr)); +}; + /** * Formats a datestring of the format YYYY-MM-DDTHH:MM:SSZ to the * following date and time format: DD.MM.YYYY HH:MM, where the time @@ -8,6 +12,7 @@ * @returns the formated date and time string */ export const formatDateToDateAndTimeString = (dateString: string): string => { + if (!isDateValid(dateString)) return ''; return new Intl.DateTimeFormat('no-NB', { year: 'numeric', month: '2-digit', From da72f4a1466688a58ac04d7cfd5f01deb9354f6e Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 22 Dec 2023 14:09:49 +0100 Subject: [PATCH 08/15] Remove duplicated types --- .../Designer/RepositoryClient/Model/User.cs | 2 +- .../app-development/layout/PageHeader.tsx | 2 +- .../layout/PageLayout.test.tsx | 27 +----- .../SettingsModal/mocks/repositoryMock.ts | 2 +- .../app-development/test/repositoryMock.ts | 4 +- frontend/dashboard/app/App.test.tsx | 8 +- .../DataModelsRepoList/DatamodelsRepoList.tsx | 16 ++-- .../components/OrgRepoList/OrgReposList.tsx | 14 +--- .../components/RepoList/RepoList.test.tsx | 33 ++++---- .../components/RepoList/RepoList.tsx | 55 +++++++----- .../ResourcesRepoList.test.tsx | 2 +- .../ResourcesRepoList/ResourcesRepoList.tsx | 2 +- .../SearchResultReposList.tsx | 23 +++-- .../ServiceOwnerSelector.tsx | 2 +- .../dashboard/data-mocks/searchedReposMock.ts | 25 ------ .../dashboard/data-mocks/starredRepoMock.ts | 18 ---- .../mutations/useSetStarredRepoMutation.ts | 4 +- .../mutations/useUnsetStarredRepoMutation.ts | 4 +- .../hooks/queries/useStarredReposQuery.ts | 7 +- .../hooks/useAugmentReposWithStarred/index.ts | 1 - .../useAugmentReposWithStarred.ts | 13 --- .../CreateService/CreateService.test.tsx | 27 +++++- .../pages/CreateService/CreateService.tsx | 2 +- .../pages/Dashboard/Dashboard.test.tsx | 18 ++-- .../dashboard/pages/Dashboard/Dashboard.tsx | 10 +-- frontend/dashboard/utils/repoUtils/index.ts | 3 +- .../utils/repoUtils/repoUtils.test.ts | 84 +------------------ .../dashboard/utils/repoUtils/repoUtils.ts | 23 ----- frontend/packages/shared/src/api/mutations.ts | 9 +- frontend/packages/shared/src/api/queries.ts | 6 +- .../AltinnHeaderProfile.test.tsx | 10 ++- .../AltinnHeaderProfile.tsx | 2 +- .../hooks/useUserNameAndOrg.test.ts | 5 +- .../hooks/useUserNameAndOrg.ts | 2 +- .../altinnHeader/AltinnHeader.test.tsx | 3 +- .../components/altinnHeader/AltinnHeader.tsx | 2 +- .../shared/src/hooks/queries/useUserQuery.ts | 2 +- frontend/packages/shared/src/mocks/mocks.ts | 40 +++------ .../packages/shared/src/mocks/queriesMock.ts | 10 +-- .../navigation/main-header/Header.test.tsx | 33 +++++--- .../src/navigation/main-header/Header.tsx | 5 +- .../main-header/HeaderMenu.test.tsx | 15 ++-- .../main-header/ProfileMenu/ProfileMenu.tsx | 2 +- .../packages/shared/src/types/Repository.ts | 6 +- frontend/packages/shared/src/types/User.ts | 7 -- .../src/types/api/SearchRepositoryResponse.ts | 4 +- frontend/packages/shared/src/types/global.ts | 19 ----- 47 files changed, 218 insertions(+), 395 deletions(-) delete mode 100644 frontend/dashboard/data-mocks/searchedReposMock.ts delete mode 100644 frontend/dashboard/data-mocks/starredRepoMock.ts delete mode 100644 frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts delete mode 100644 frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts delete mode 100644 frontend/packages/shared/src/types/User.ts diff --git a/backend/src/Designer/RepositoryClient/Model/User.cs b/backend/src/Designer/RepositoryClient/Model/User.cs index e49d0175d7f..4b190519738 100644 --- a/backend/src/Designer/RepositoryClient/Model/User.cs +++ b/backend/src/Designer/RepositoryClient/Model/User.cs @@ -79,7 +79,7 @@ public User() /// /// Sets /// - [DataMember(Name = "UserType", EmitDefaultValue = false)] + [DataMember(Name = "userType", EmitDefaultValue = false)] public UserType UserType { get; set; } /// diff --git a/frontend/app-development/layout/PageHeader.tsx b/frontend/app-development/layout/PageHeader.tsx index 8754f6398ff..3af2a5f9f9c 100644 --- a/frontend/app-development/layout/PageHeader.tsx +++ b/frontend/app-development/layout/PageHeader.tsx @@ -8,7 +8,7 @@ import { AltinnButtonActionItem } from 'app-shared/components/altinnHeader/types import { GiteaHeader } from 'app-shared/components/GiteaHeader'; import { SettingsModalButton } from './SettingsModalButton'; import { TopBarMenu } from 'app-shared/enums/TopBarMenu'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; type SubMenuContentProps = { org: string; diff --git a/frontend/app-development/layout/PageLayout.test.tsx b/frontend/app-development/layout/PageLayout.test.tsx index 0a73d4c7361..f7e27a26f1d 100644 --- a/frontend/app-development/layout/PageLayout.test.tsx +++ b/frontend/app-development/layout/PageLayout.test.tsx @@ -5,29 +5,12 @@ import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../test/testUtils'; import { textMock } from '../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; -import { RepoStatus } from 'app-shared/types/RepoStatus'; -import { User } from 'app-shared/types/User'; import { RoutePaths } from 'app-development/enums/RoutePaths'; +import { repoStatus } from 'app-shared/mocks/mocks'; const mockOrg: string = 'org'; const mockApp: string = 'app'; -const mockRepoStatus: RepoStatus = { - aheadBy: 0, - behindBy: 0, - contentStatus: [], - hasMergeConflict: false, - repositoryStatus: 'Ok', -}; - -const mockUser: User = { - avatar_url: 'test', - email: 'test@test.com', - full_name: 'Mock Tester', - id: 1, - login: 'MT1', -}; - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ @@ -60,7 +43,7 @@ describe('PageLayout', () => { it('renders "MergeConflictWarning" when repoStatus has merge conflict', async () => { render({ - getRepoStatus: () => Promise.resolve({ ...mockRepoStatus, hasMergeConflict: true }), + getRepoStatus: () => Promise.resolve({ ...repoStatus, hasMergeConflict: true }), }); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); @@ -83,11 +66,7 @@ describe('PageLayout', () => { }); const resolveAndWaitForSpinnerToDisappear = async (queries: Partial = {}) => { - render({ - ...queries, - getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve(mockRepoStatus)), - getUser: jest.fn().mockImplementation(() => Promise.resolve(mockUser)), - }); + render(queries); await waitForElementToBeRemoved(() => screen.queryByTitle(textMock('general.loading'))); }; diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts b/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts index 4e5b8fba92a..e32e821dce6 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts @@ -21,7 +21,7 @@ export const mockRepository1: Repository = { full_name: 'Mons Monsen', id: 234, login: 'Mons', - UserType: 2, + userType: 2, }, permissions: { admin: true, diff --git a/frontend/app-development/test/repositoryMock.ts b/frontend/app-development/test/repositoryMock.ts index 45b4d062656..31cb2b0811c 100644 --- a/frontend/app-development/test/repositoryMock.ts +++ b/frontend/app-development/test/repositoryMock.ts @@ -21,7 +21,7 @@ export const repositoryMock: Repository = { full_name: '', id: 0, login: '', - UserType: 0, + userType: 0, }, permissions: { admin: true, @@ -36,4 +36,4 @@ export const repositoryMock: Repository = { updated_at: '', watchers_count: 0, website: '', -} +}; diff --git a/frontend/dashboard/app/App.test.tsx b/frontend/dashboard/app/App.test.tsx index 2a7fc1c78d8..efc767794ae 100644 --- a/frontend/dashboard/app/App.test.tsx +++ b/frontend/dashboard/app/App.test.tsx @@ -10,12 +10,11 @@ const renderWithMockServices = (services: Partial = {}) => render( - + , ); }; describe('App', () => { - test('should display spinner while loading', () => { renderWithMockServices(); expect(screen.getByText(textMock('general.loading'))).toBeInTheDocument(); @@ -27,7 +26,7 @@ describe('App', () => { await screen.findByRole('heading', { level: 1, name: 'Feil oppstod ved innlasting av brukerdata', - }) + }), ).toBeInTheDocument(); }); @@ -38,14 +37,13 @@ describe('App', () => { await screen.findByRole('heading', { level: 1, name: 'Feil oppstod ved innlasting av organisasjoner', - }) + }), ); }); test('should display dashboard page if successfully loading data', async () => { renderWithMockServices(); await waitForElementToBeRemoved(screen.queryByText(textMock('general.loading'))); - await waitForElementToBeRemoved(screen.queryByText(textMock('general.loading'))); expect(screen.getByRole('heading', { level: 2, name: textMock('dashboard.favourites') })); expect(screen.getByRole('heading', { level: 2, name: textMock('dashboard.my_apps') })); expect(screen.getByRole('heading', { level: 2, name: textMock('dashboard.resources') })); diff --git a/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx b/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx index a9d1e6fc1e9..50528ee2a33 100644 --- a/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx +++ b/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx @@ -2,19 +2,18 @@ import React from 'react'; import { RepoList } from '../RepoList'; import { getReposLabel } from '../../utils/repoUtils'; import { getUidFilter } from '../../utils/filterUtils'; -import { useAugmentReposWithStarred } from '../../hooks/useAugmentReposWithStarred'; import { useTranslation } from 'react-i18next'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; import { useSearchReposQuery } from 'dashboard/hooks/queries/useSearchReposQuery'; -import { IRepository } from 'app-shared/types/global'; +import { Repository } from 'app-shared/types/Repository'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; import { Heading } from '@digdir/design-system-react'; type DataModelsReposListProps = { user: User; organizations: Organization[]; - starredRepos: IRepository[]; + starredRepos: Repository[]; }; export const DatamodelsReposList = ({ user, @@ -36,12 +35,7 @@ export const DatamodelsReposList = ({ page: 0, }); - const reposWithStarred = useAugmentReposWithStarred({ - repos: repos?.data, - starredRepos, - }); - - if (!reposWithStarred.length) { + if (!repos?.data.length) { return null; } @@ -50,7 +44,7 @@ export const DatamodelsReposList = ({ {getReposLabel({ selectedContext, orgs: organizations, t, isDatamodelsRepo: true })} - + ); }; diff --git a/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx b/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx index d976ed2c55d..353f6a5b02a 100644 --- a/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx +++ b/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx @@ -2,11 +2,9 @@ import React from 'react'; import { RepoList } from '../RepoList'; import { getReposLabel } from '../../utils/repoUtils'; import { getUidFilter } from '../../utils/filterUtils'; -import { useAugmentReposWithStarred } from '../../hooks/useAugmentReposWithStarred'; import { useTranslation } from 'react-i18next'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; -import { IRepository } from 'app-shared/types/global'; import { useReposSearch } from 'dashboard/hooks/useReposSearch'; import { DATAGRID_ROWS_PER_PAGE_OPTIONS } from '../../constants'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; @@ -15,9 +13,8 @@ import { Heading } from '@digdir/design-system-react'; type OrgReposListProps = { user: User; organizations: Organization[]; - starredRepos: IRepository[]; }; -export const OrgReposList = ({ user, organizations, starredRepos }: OrgReposListProps) => { +export const OrgReposList = ({ user, organizations }: OrgReposListProps) => { const selectedContext = useSelectedContext(); const { t } = useTranslation(); const uid = getUidFilter({ selectedContext, userId: user.id, organizations }); @@ -32,18 +29,13 @@ export const OrgReposList = ({ user, organizations, starredRepos }: OrgReposList setPageSize, } = useReposSearch({ uid: uid as number, defaultPageSize: 5 }); - const reposWithStarred = useAugmentReposWithStarred({ - repos: searchResults?.data, - starredRepos, - }); - return (
{getReposLabel({ selectedContext, orgs: organizations, t })} !repo.name.endsWith('-datamodels'))} + repos={searchResults?.data.filter((repo) => !repo.name.endsWith('-datamodels'))} isLoading={isLoadingSearchResults} onPageSizeChange={setPageSize} isServerSort={true} diff --git a/frontend/dashboard/components/RepoList/RepoList.test.tsx b/frontend/dashboard/components/RepoList/RepoList.test.tsx index 2b2e01e60cb..e8a5588636e 100644 --- a/frontend/dashboard/components/RepoList/RepoList.test.tsx +++ b/frontend/dashboard/components/RepoList/RepoList.test.tsx @@ -2,27 +2,26 @@ import React from 'react'; import { act, screen, render, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MockServicesContextWrapper } from '../../dashboardTestUtils'; -import { starredRepoMock } from '../../data-mocks/starredRepoMock'; import { IRepoListProps, RepoList } from './RepoList'; -import { IRepository } from 'app-shared/types/global'; +import type { Repository } from 'app-shared/types/Repository'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { textMock } from '../../../testing/mocks/i18nMock'; +import { repository } from 'app-shared/mocks/mocks'; const user = userEvent.setup(); const renderWithMockServices = ( componentProps: IRepoListProps, - services?: Partial + services?: Partial, ) => { render( - - + + , ); }; describe('RepoList', () => { - test('should not call onSortModelChange when clicking sort button and isServerSort is false', async () => { const handleSortMock = jest.fn(); renderWithMockServices({ @@ -56,14 +55,20 @@ describe('RepoList', () => { }); }); - test("Should render GridActionsCellItem", () => { - renderWithMockServices({ - isLoading: false, - isServerSort: true, - rowCount: 5, - }); - const gridActionsCellItem = within(screen.getByRole('menuitem', - { name: textMock('dashboard.unstar') })).getByRole('img'); + test('Should render GridActionsCellItem', async () => { + const getStarredRepos = jest + .fn() + .mockImplementation(() => Promise.resolve([repository])); + renderWithMockServices( + { + isLoading: false, + isServerSort: true, + rowCount: 5, + }, + { getStarredRepos }, + ); + const unstar = await screen.findByRole('menuitem', { name: textMock('dashboard.unstar') }); + const gridActionsCellItem = within(unstar).getByRole('img'); expect(gridActionsCellItem).toBeInTheDocument(); }); }); diff --git a/frontend/dashboard/components/RepoList/RepoList.tsx b/frontend/dashboard/components/RepoList/RepoList.tsx index 686f6deeb0d..97d128fdbb0 100644 --- a/frontend/dashboard/components/RepoList/RepoList.tsx +++ b/frontend/dashboard/components/RepoList/RepoList.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useRef, useState } from 'react'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; import type { GridActionsColDef, GridColDef, @@ -10,13 +10,13 @@ import type { } from '@mui/x-data-grid'; import { DataGrid, GridActionsCellItem, GridOverlay } from '@mui/x-data-grid'; import cn from 'classnames'; -import type { IRepository } from 'app-shared/types/global'; +import type { Repository } from 'app-shared/types/Repository'; import { MakeCopyModal } from '../MakeCopyModal'; import { getRepoEditUrl } from '../../utils/urlUtils'; import { useTranslation } from 'react-i18next'; import { DATAGRID_DEFAULT_PAGE_SIZE } from '../../constants'; import classes from './RepoList.module.css'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { useSetStarredRepoMutation } from '../../hooks/mutations'; import { useUnsetStarredRepoMutation } from '../../hooks/mutations'; import { @@ -24,13 +24,13 @@ import { FilesIcon, ExternalLinkIcon, StarIcon, - StarFillIcon + StarFillIcon, } from '@navikt/aksel-icons'; - +import { useStarredReposQuery } from 'dashboard/hooks/queries'; export interface IRepoListProps { isLoading: boolean; - repos?: IRepository[]; + repos?: Repository[]; isServerSort?: boolean; pageSize?: number; rowCount: number; @@ -46,7 +46,7 @@ const defaultRowsPerPageOptions = [DATAGRID_DEFAULT_PAGE_SIZE]; const isRowSelectable = () => false; -const defaultArray: IRepository[] = []; +const defaultArray: Repository[] = []; const gridStyleOverride = { border: 'none', @@ -88,6 +88,7 @@ export const RepoList = ({ sortModel, disableVirtualization = false, }: IRepoListProps) => { + const { data: userStarredRepos, isPending: areUserStarredReposPending } = useStarredReposQuery(); const [copyCurrentRepoName, setCopyCurrentRepoName] = useState(''); const { mutate: setStarredRepo } = useSetStarredRepoMutation(); @@ -95,6 +96,11 @@ export const RepoList = ({ const copyModalAnchorRef = useRef(null); const { t } = useTranslation(); + const isRepoStarred = useCallback( + (repoId: number) => userStarredRepos?.some((starredRepo) => starredRepo.id === repoId), + [userStarredRepos], + ); + const cols = useMemo(() => { const favouriteActionCol: GridActionsColDef = { field: '', @@ -104,9 +110,11 @@ export const RepoList = ({ headerClassName: classes.columnHeader, width: 50, getActions: (params: GridRowParams) => { - const repo = params.row as IRepository; + const repo = params.row as Repository; + const isStarred = isRepoStarred(repo.id); + const handleToggleFav = () => { - if (repo.user_has_starred) { + if (isStarred) { unsetStarredRepo(repo); } else { setStarredRepo(repo); @@ -118,11 +126,15 @@ export const RepoList = ({ key={repo.id} id={`fav-repo-${repo.id}`} onClick={handleToggleFav} - label={repo.user_has_starred ? t('dashboard.unstar') : t('dashboard.star')} - icon={ repo.user_has_starred - ? - : } - /> + label={isStarred ? t('dashboard.unstar') : t('dashboard.star')} + icon={ + isStarred ? ( + + ) : ( + + ) + } + />, ]; }, }; @@ -188,7 +200,12 @@ export const RepoList = ({ />, } + icon={ + + } key={`dashboard.edit_app${params.row.id}`} label={t('dashboard.edit_app')} onClick={() => (window.location.href = editUrl)} @@ -224,7 +241,7 @@ export const RepoList = ({ ]; return [favouriteActionCol, ...columns, ...actionsCol]; - }, [setStarredRepo, t, unsetStarredRepo]); + }, [isRepoStarred, setStarredRepo, t, unsetStarredRepo]); const handleCloseCopyModal = () => setCopyCurrentRepoName(null); @@ -234,7 +251,7 @@ export const RepoList = ({ labelRowsPerPage: t('dashboard.rows_per_page'), }, }), - [t] + [t], ); return ( @@ -246,7 +263,7 @@ export const RepoList = ({ }} componentsProps={componentPropsLabelOverrides} autoHeight={true} - loading={isLoading} + loading={isLoading || areUserStarredReposPending} rows={repos} columns={cols} pageSize={pageSize} @@ -270,7 +287,7 @@ export const RepoList = ({ NoRowsOverlay: NoResults, }} autoHeight={true} - loading={isLoading} + loading={isLoading || areUserStarredReposPending} rows={repos} columns={cols} pageSize={pageSize} diff --git a/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.test.tsx b/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.test.tsx index 0a83273ea31..6a897070e7a 100644 --- a/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.test.tsx +++ b/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.test.tsx @@ -5,7 +5,7 @@ import { ResourcesRepoList } from './ResourcesRepoList'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { textMock } from '../../../testing/mocks/i18nMock'; import { useParams } from 'react-router-dom'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { MockServicesContextWrapper } from 'dashboard/dashboardTestUtils'; const originalWindowLocation = window.location; diff --git a/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.tsx b/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.tsx index 28187d0066d..985d18747a7 100644 --- a/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.tsx +++ b/frontend/dashboard/components/ResourcesRepoList/ResourcesRepoList.tsx @@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'; import { StudioSpinner } from '@studio/components'; import { Alert, Heading, Link } from '@digdir/design-system-react'; import { useSearchReposQuery } from 'dashboard/hooks/queries'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { getUidFilter } from 'dashboard/utils/filterUtils'; type ResourcesRepoListProps = { diff --git a/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx b/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx index 18f72bbc39f..fd7e96e6906 100644 --- a/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx +++ b/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx @@ -1,30 +1,29 @@ import React from 'react'; -import { useAugmentReposWithStarred } from '../../hooks/useAugmentReposWithStarred'; import { RepoList } from '../RepoList'; import { useTranslation } from 'react-i18next'; import { useReposSearch } from 'dashboard/hooks/useReposSearch'; import { DATAGRID_ROWS_PER_PAGE_OPTIONS } from '../../constants'; -import { IRepository } from 'app-shared/types/global'; type SearchResultReposList = { - starredRepos: IRepository[]; searchValue: string; }; -export const SearchResultReposList = ({ starredRepos, searchValue }: SearchResultReposList) => { +export const SearchResultReposList = ({ searchValue }: SearchResultReposList) => { const { t } = useTranslation(); - const { searchResults, isLoadingSearchResults, sortModel, pageSize, setPageNumber, setSortModel, setPageSize } = - useReposSearch({ keyword: searchValue }); - - const reposWithStarred = useAugmentReposWithStarred({ - repos: searchResults?.data, - starredRepos, - }); + const { + searchResults, + isLoadingSearchResults, + sortModel, + pageSize, + setPageNumber, + setSortModel, + setPageSize, + } = useReposSearch({ keyword: searchValue }); return (

{t('dashboard.search_result')}

{ const { setStarredRepo } = useServicesContext(); const queryClient = useQueryClient(); return useMutation({ - mutationFn: (repo: IRepository) => setStarredRepo(repo), + mutationFn: (repo: Repository) => setStarredRepo(repo.owner.login, repo.name), onSuccess: () => queryClient.invalidateQueries({ queryKey: [QueryKey.StarredRepos] }), }); }; diff --git a/frontend/dashboard/hooks/mutations/useUnsetStarredRepoMutation.ts b/frontend/dashboard/hooks/mutations/useUnsetStarredRepoMutation.ts index 3e19c3b8747..997201fd197 100644 --- a/frontend/dashboard/hooks/mutations/useUnsetStarredRepoMutation.ts +++ b/frontend/dashboard/hooks/mutations/useUnsetStarredRepoMutation.ts @@ -1,13 +1,13 @@ import { useServicesContext } from 'app-shared/contexts/ServicesContext'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { IRepository } from 'app-shared/types/global'; +import { Repository } from 'app-shared/types/Repository'; import { QueryKey } from 'app-shared/types/QueryKey'; export const useUnsetStarredRepoMutation = () => { const { unsetStarredRepo } = useServicesContext(); const queryClient = useQueryClient(); return useMutation({ - mutationFn: (repo: IRepository) => unsetStarredRepo(repo), + mutationFn: (repo: Repository) => unsetStarredRepo(repo.owner.login, repo.name), onSuccess: () => queryClient.invalidateQueries({ queryKey: [QueryKey.StarredRepos] }), }); }; diff --git a/frontend/dashboard/hooks/queries/useStarredReposQuery.ts b/frontend/dashboard/hooks/queries/useStarredReposQuery.ts index 1c4273d550f..e1c67944f46 100644 --- a/frontend/dashboard/hooks/queries/useStarredReposQuery.ts +++ b/frontend/dashboard/hooks/queries/useStarredReposQuery.ts @@ -1,13 +1,12 @@ import { useServicesContext } from 'app-shared/contexts/ServicesContext'; import { useQuery, UseQueryResult } from '@tanstack/react-query'; import { QueryKey } from 'app-shared/types/QueryKey'; -import { IRepository } from 'app-shared/types/global'; +import { Repository } from 'app-shared/types/Repository'; -export const useStarredReposQuery = (): UseQueryResult => { +export const useStarredReposQuery = (): UseQueryResult => { const { getStarredRepos } = useServicesContext(); return useQuery({ queryKey: [QueryKey.StarredRepos], - queryFn: () => - getStarredRepos().then((data) => data.map((repo) => ({ ...repo, user_has_starred: true }))), + queryFn: () => getStarredRepos(), }); }; diff --git a/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts b/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts deleted file mode 100644 index 2c75fe37b59..00000000000 --- a/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useAugmentReposWithStarred } from './useAugmentReposWithStarred'; diff --git a/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts b/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts deleted file mode 100644 index cd31a1da370..00000000000 --- a/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useMemo } from 'react'; -import type { MergeReposProps } from '../../utils/repoUtils'; -import { mergeRepos } from '../../utils/repoUtils'; -import type { IRepository } from 'app-shared/types/global'; - -export const useAugmentReposWithStarred = ({ - repos, - starredRepos, -}: MergeReposProps): IRepository[] => { - return useMemo(() => { - return mergeRepos({ repos, starredRepos }); - }, [repos, starredRepos]); -}; diff --git a/frontend/dashboard/pages/CreateService/CreateService.test.tsx b/frontend/dashboard/pages/CreateService/CreateService.test.tsx index 499ff3d8f95..69bb3a28e61 100644 --- a/frontend/dashboard/pages/CreateService/CreateService.test.tsx +++ b/frontend/dashboard/pages/CreateService/CreateService.test.tsx @@ -3,8 +3,8 @@ import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MockServicesContextWrapper } from '../../dashboardTestUtils'; import { CreateService } from './CreateService'; -import { User } from 'app-shared/types/User'; -import { IGiteaOrganisation, IRepository } from 'app-shared/types/global'; +import { Repository, User } from 'app-shared/types/Repository'; +import { IGiteaOrganisation } from 'app-shared/types/global'; import { textMock } from '../../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; @@ -15,21 +15,38 @@ const orgMock: IGiteaOrganisation = { full_name: 'unit-test', }; -const repositoryMock: IRepository = { +const repositoryMock: Repository = { clone_url: '', description: '', full_name: 'test', html_url: '', id: 0, is_cloned_to_local: false, - user_has_starred: false, name: 'test', owner: { avatar_url: '', full_name: '', login: '', + email: '', + id: 0, + userType: 0, }, updated_at: '', + created_at: '', + default_branch: '', + empty: false, + fork: false, + forks_count: 0, + mirror: false, + open_issues_count: 0, + permissions: undefined, + private: false, + repositoryCreatedStatus: 0, + size: 0, + ssh_url: '', + stars_count: 0, + watchers_count: 0, + website: '', }; const userMock: User = { @@ -38,6 +55,7 @@ const userMock: User = { email: 'tester@tester.test', full_name: 'Tester Testersen', login: 'tester', + userType: 0, }; jest.mock('react-router-dom', () => ({ @@ -61,6 +79,7 @@ const renderWithMockServices = ( email: '', full_name: '', login: '', + userType: 0, } } /> diff --git a/frontend/dashboard/pages/CreateService/CreateService.tsx b/frontend/dashboard/pages/CreateService/CreateService.tsx index a23999ff77d..f705516babf 100644 --- a/frontend/dashboard/pages/CreateService/CreateService.tsx +++ b/frontend/dashboard/pages/CreateService/CreateService.tsx @@ -6,7 +6,7 @@ import classes from './CreateService.module.css'; import { Button } from '@digdir/design-system-react'; import { useTranslation } from 'react-i18next'; import { Organization } from 'app-shared/types/Organization'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { useAddRepoMutation } from 'dashboard/hooks/mutations/useAddRepoMutation'; import { DatamodelFormat } from 'app-shared/types/DatamodelFormat'; import { SelectedContextType } from 'app-shared/navigation/main-header/Header'; diff --git a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx index f0244f38427..16dfcf57a24 100644 --- a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx +++ b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx @@ -3,11 +3,11 @@ import { render, screen, waitForElementToBeRemoved } from '@testing-library/reac import { MockServicesContextWrapper } from '../../dashboardTestUtils'; import { Dashboard } from './Dashboard'; import { textMock } from '../../../testing/mocks/i18nMock'; -import { User } from 'app-shared/types/User'; -import { starredRepoMock } from '../../data-mocks/starredRepoMock'; -import { searchedRepos } from '../../data-mocks/searchedReposMock'; +import { Repository, User } from 'app-shared/types/Repository'; import { SelectedContextType } from 'app-shared/navigation/main-header/Header'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; +import { repository, searchRepositoryResponse } from 'app-shared/mocks/mocks'; +import { SearchRepositoryResponse } from 'app-shared/types/api'; const renderWithMockServices = (services?: Partial) => { render( @@ -36,7 +36,9 @@ describe('Dashboard', () => { }); test('should display favorite list with one item', async () => { - renderWithMockServices({ getStarredRepos: () => Promise.resolve([starredRepoMock]) }); + renderWithMockServices({ + getStarredRepos: () => Promise.resolve([repository]), + }); await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); expect( await screen.findAllByRole('menuitem', { name: textMock('dashboard.unstar') }), @@ -44,7 +46,13 @@ describe('Dashboard', () => { }); test('should display list of my application', async () => { - renderWithMockServices({ searchRepos: () => Promise.resolve(searchedRepos) }); + renderWithMockServices({ + searchRepos: () => + Promise.resolve({ + ...searchRepositoryResponse, + data: [repository], + }), + }); await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); expect( await screen.findAllByRole('menuitem', { name: textMock('dashboard.star') }), diff --git a/frontend/dashboard/pages/Dashboard/Dashboard.tsx b/frontend/dashboard/pages/Dashboard/Dashboard.tsx index 680f57a441c..7aa1cc05c7e 100644 --- a/frontend/dashboard/pages/Dashboard/Dashboard.tsx +++ b/frontend/dashboard/pages/Dashboard/Dashboard.tsx @@ -15,7 +15,7 @@ import { Footer } from '../../components/Footer'; import { Link } from 'react-router-dom'; import { useDebounce } from 'react-use'; import { useTranslation } from 'react-i18next'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; import { useStarredReposQuery } from '../../hooks/queries'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; @@ -94,16 +94,12 @@ export const Dashboard = ({ user, organizations, disableDebounce }: DashboardPro
{debouncedSearchText ? ( - + ) : ( <>
- +
{ }); }); -describe('mergeRepos', () => { - const repoData = { - name: 'repo', - full_name: 'repo_fullname', - owner: { - avatar_url: 'url', - login: 'login', - full_name: 'full_name', - }, - description: 'description', - is_cloned_to_local: false, - updated_at: 'today', - html_url: 'html_url', - clone_url: 'clone_url', - user_has_starred: false, - }; - - it('should set user_has_starred to true when ids for repos in both lists match', () => { - const result = mergeRepos({ - repos: [ - { - ...repoData, - id: 1, - }, - { - ...repoData, - id: 2, - }, - ], - starredRepos: [ - { - ...repoData, - id: 2, - user_has_starred: true, - }, - ], - }); - - expect(result).toEqual([ - { - ...repoData, - id: 1, - user_has_starred: false, - }, - { - ...repoData, - id: 2, - user_has_starred: true, - }, - ]); - }); - - it('should return empty array when no repos are passed', () => { - const result = mergeRepos({ - repos: undefined, - starredRepos: undefined, - }); - - expect(result).toEqual([]); - }); - - it('should return original repos array when starred repos are undefined', () => { - const repos = [ - { - ...repoData, - id: 1, - }, - { - ...repoData, - id: 2, - }, - ]; - - const result = mergeRepos({ - repos, - starredRepos: undefined, - }); - - expect(result).toEqual(repos); - }); -}); - describe('validateRepoName', () => { it('should return true when repo name does not contain invalid characters', () => { expect(validateRepoName('repo')).toBe(true); diff --git a/frontend/dashboard/utils/repoUtils/repoUtils.ts b/frontend/dashboard/utils/repoUtils/repoUtils.ts index d9a45eae233..814299e510b 100644 --- a/frontend/dashboard/utils/repoUtils/repoUtils.ts +++ b/frontend/dashboard/utils/repoUtils/repoUtils.ts @@ -1,5 +1,4 @@ import { SelectedContextType } from 'app-shared/navigation/main-header/Header'; -import type { IRepository } from 'app-shared/types/global'; import { Organization } from 'app-shared/types/Organization'; import i18next from 'i18next'; @@ -11,11 +10,6 @@ type GetReposLabel = { isResourcesRepo?: boolean; }; -export type MergeReposProps = { - repos?: IRepository[]; - starredRepos: IRepository[]; -}; - type TranslationMapKey = SelectedContextType | 'named_org' | 'org'; type TranslationMap = Record; const appsTranslationMap: TranslationMap = { @@ -64,23 +58,6 @@ export const getReposLabel = ({ : t(concatenatedTranslationMap.org); }; -export const mergeRepos = ({ repos, starredRepos }: MergeReposProps) => { - if (!repos) { - return []; - } - - if (!starredRepos) { - return repos; - } - - return repos.map((repo) => { - return { - ...repo, - user_has_starred: !!starredRepos.find((starredRepo) => starredRepo.id === repo.id), - }; - }); -}; - export const validateRepoName = (repoName: string) => { const appNameRegex = /^(?!datamodels$)[a-z][a-z0-9-]{1,28}[a-z0-9]$/; return appNameRegex.test(repoName); diff --git a/frontend/packages/shared/src/api/mutations.ts b/frontend/packages/shared/src/api/mutations.ts index 490059ec206..a894d546cbb 100644 --- a/frontend/packages/shared/src/api/mutations.ts +++ b/frontend/packages/shared/src/api/mutations.ts @@ -40,7 +40,7 @@ import { CreateReleasePayload } from 'app-shared/types/api/CreateReleasePayload' import { CreateRepoCommitPayload } from 'app-shared/types/api/CreateRepoCommitPayload'; import { ExternalFormLayout } from 'app-shared/types/api/FormLayoutsResponse'; import { LayoutSetConfig, LayoutSets } from 'app-shared/types/api/LayoutSetsResponse'; -import { ILayoutSettings, IRepository, ITextResourcesObjectFormat } from 'app-shared/types/global'; +import { ILayoutSettings, ITextResourcesObjectFormat } from 'app-shared/types/global'; import { RuleConfig } from 'app-shared/types/RuleConfig'; import { UpdateTextIdPayload } from 'app-shared/types/api/UpdateTextIdPayload'; import { buildQueryParams } from 'app-shared/utils/urlUtils'; @@ -50,6 +50,7 @@ import type { Policy } from '@altinn/policy-editor'; import type { NewResource, Resource } from 'app-shared/types/ResourceAdm'; import { ApplicationMetadata } from 'app-shared/types/ApplicationMetadata'; import { AppConfig } from 'app-shared/types/AppConfig'; +import { Repository } from 'app-shared/types/Repository'; const headers = { Accept: 'application/json', @@ -59,7 +60,7 @@ const headers = { export const addAppAttachmentMetadata = (org: string, app: string, payload: ApplicationAttachmentMetadata) => post(appMetadataAttachmentPath(org, app), payload); export const addLanguageCode = (org: string, app: string, language: string, payload: AddLanguagePayload) => post(textResourcesPath(org, app, language), payload); export const addLayoutSet = (org: string, app: string, payload: LayoutSetConfig) => put(layoutSetsPath(org, app), payload); -export const addRepo = (repoToAdd: AddRepoParams) => post(`${createRepoPath()}${buildQueryParams(repoToAdd)}`); +export const addRepo = (repoToAdd: AddRepoParams) => post(`${createRepoPath()}${buildQueryParams(repoToAdd)}`); export const addXsdFromRepo = (org: string, app: string, modelPath: string) => post(datamodelAddXsdFromRepoPath(org, app, modelPath)); export const commitAndPushChanges = (org: string, app: string, payload: CreateRepoCommitPayload) => post(repoCommitPushPath(org, app), payload, { headers }); export const configureLayoutSet = (org: string, app: string, layoutSetName: string) => post(layoutSetPath(org, app, layoutSetName)); @@ -80,8 +81,8 @@ export const saveDatamodel = (org: string, app: string, modelPath: string, paylo export const saveFormLayout = (org: string, app: string, layoutName: string, layoutSetName: string, payload: ExternalFormLayout) => post(formLayoutPath(org, app, layoutName, layoutSetName), payload); export const saveFormLayoutSettings = (org: string, app: string, layoutSetName: string, payload: ILayoutSettings) => post(layoutSettingsPath(org, app, layoutSetName), payload); export const saveRuleConfig = (org: string, app: string, layoutSetName: string, payload: RuleConfig) => post(ruleConfigPath(org, app, layoutSetName), payload); -export const setStarredRepo = (repo: IRepository) => put(userStarredRepoPath(repo.owner.login, repo.name), {}); -export const unsetStarredRepo = (repo: IRepository) => del(userStarredRepoPath(repo.owner.login, repo.name)); +export const setStarredRepo = (org: string, app: string) => put(userStarredRepoPath(org, app), {}); +export const unsetStarredRepo = (org: string, app: string) => del(userStarredRepoPath(org, app)); export const updateAppAttachmentMetadata = (org: string, app: string, payload: ApplicationAttachmentMetadata) => put(appMetadataAttachmentPath(org, app), payload); export const updateFormLayoutName = (org: string, app: string, oldName: string, newName: string, layoutSetName: string) => post(formLayoutNamePath(org, app, oldName, layoutSetName), JSON.stringify(newName), { headers: { 'Content-Type': 'application/json' } }); export const updateTextId = (org: string, app: string, payload: UpdateTextIdPayload) => put(textResourceIdsPath(org, app), payload); diff --git a/frontend/packages/shared/src/api/queries.ts b/frontend/packages/shared/src/api/queries.ts index 1711f7aa980..1e6c3acae93 100644 --- a/frontend/packages/shared/src/api/queries.ts +++ b/frontend/packages/shared/src/api/queries.ts @@ -49,13 +49,13 @@ import { DatamodelMetadataJson, DatamodelMetadataXsd } from 'app-shared/types/Da import { DeployEnvironment } from 'app-shared/types/DeployEnvironment'; import { FormLayoutsResponse } from 'app-shared/types/api/FormLayoutsResponse'; import { LayoutSets } from 'app-shared/types/api/LayoutSetsResponse'; -import { ILayoutSettings, IRepository, ITextResourcesWithLanguage, IFrontEndSettings } from 'app-shared/types/global'; +import { ILayoutSettings, ITextResourcesWithLanguage, IFrontEndSettings } from 'app-shared/types/global'; import { Organization } from 'app-shared/types/Organization'; import { OrgsState } from 'app-shared/types/OrgsState'; import { RepoStatus } from 'app-shared/types/RepoStatus'; import { Repository } from 'app-shared/types/Repository'; import { RuleConfig } from 'app-shared/types/RuleConfig'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { WidgetSettingsResponse } from 'app-shared/types/widgetTypes'; import { buildQueryParams } from 'app-shared/utils/urlUtils'; import { componentSchemaUrl, expressionSchemaUrl, layoutSchemaUrl, newsListUrl, numberFormatSchemaUrl, orgsListUrl } from '../cdn-paths'; @@ -98,7 +98,7 @@ export const getRepoPull = (owner: string, app: string) => get(repoP export const getRepoStatus = (owner: string, app: string) => get(repoStatusPath(owner, app)); export const getRuleConfig = (owner: string, app: string, layoutSetName: string) => get(ruleConfigPath(owner, app, layoutSetName)); export const getRuleModel = (owner: string, app: string, layoutSetName: string) => get(ruleHandlerPath(owner, app, layoutSetName)); -export const getStarredRepos = () => get(userStarredListPath()); +export const getStarredRepos = () => get(userStarredListPath()); export const getTextLanguages = (owner: string, app: string): Promise => get(textLanguagesPath(owner, app)); export const getTextResources = (owner: string, app: string, lang: string) => get(textResourcesPath(owner, app, lang)); export const getUser = () => get(userCurrentPath()); diff --git a/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.test.tsx b/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.test.tsx index 83b3e0d9fb6..66ef3ff7827 100644 --- a/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.test.tsx +++ b/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.test.tsx @@ -18,6 +18,7 @@ describe('AltinnHeaderProfile', () => { full_name: 'Test User', id: 1, login: 'test-user', + userType: 0, }, }); expect(screen.queryByText('test-user')).not.toBeInTheDocument(); @@ -26,7 +27,11 @@ describe('AltinnHeaderProfile', () => { it('should render users name and name of org the user represents', () => { render({ org: 'test-org' }); - expect(screen.getByText(textMock('shared.header_user_for_org', { user: 'test-user', org: 'Test Org' }))).toBeInTheDocument(); + expect( + screen.getByText( + textMock('shared.header_user_for_org', { user: 'test-user', org: 'Test Org' }), + ), + ).toBeInTheDocument(); }); }); @@ -47,7 +52,7 @@ export const render = (props?: Partial) => { login: 'test-org', email: 'test-email', id: 1, - UserType: 1, + userType: 1, }, updated_at: 'never', created_at: 'now', @@ -76,6 +81,7 @@ export const render = (props?: Partial) => { full_name: undefined, id: 1, login: 'test-user', + userType: 0, }, }; diff --git a/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.tsx b/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.tsx index e941e42e2af..2ce6440dc37 100644 --- a/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.tsx +++ b/frontend/packages/shared/src/components/AltinnHeaderProfile/AltinnHeaderProfile.tsx @@ -1,6 +1,6 @@ import { ProfileMenu } from 'app-shared/navigation/main-header/ProfileMenu'; import { Repository } from 'app-shared/types/Repository'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import React, { ReactNode } from 'react'; import classes from './AltinnHeaderProfile.module.css'; import { useUserNameAndOrg } from './hooks/useUserNameAndOrg'; diff --git a/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.test.ts b/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.test.ts index 93b66b5f9e7..61081433a7c 100644 --- a/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.test.ts +++ b/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.test.ts @@ -1,6 +1,6 @@ import { textMock } from '../../../../../../testing/mocks/i18nMock'; import { useUserNameAndOrg } from './useUserNameAndOrg'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { Repository } from 'app-shared/types/Repository'; const mockOrg: string = 'org'; @@ -11,6 +11,7 @@ const mockUser: User = { id: 1, login: 'testUser', full_name: 'Test User', + userType: 0, }; const mockRepository: Repository = { @@ -34,7 +35,7 @@ const mockRepository: Repository = { full_name: 'Name Test', id: 0, login: '', - UserType: 0, + userType: 0, }, permissions: { admin: true, diff --git a/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.ts b/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.ts index 53209c0b4be..864821eff13 100644 --- a/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.ts +++ b/frontend/packages/shared/src/components/AltinnHeaderProfile/hooks/useUserNameAndOrg.ts @@ -1,5 +1,5 @@ import { Repository } from 'app-shared/types/Repository'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { useTranslation } from 'react-i18next'; /** diff --git a/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.test.tsx b/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.test.tsx index 0cebb1128f6..ea223d4feba 100644 --- a/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.test.tsx +++ b/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.test.tsx @@ -74,6 +74,7 @@ const render = (props: Partial = {}) => { full_name: 'Test Testesen', id: 1, login: 'username', + userType: 0, }, repository: { clone_url: 'clone_url', @@ -89,7 +90,7 @@ const render = (props: Partial = {}) => { login: 'test-org', email: 'test-email', id: 1, - UserType: 1, + userType: 1, }, updated_at: 'never', created_at: 'now', diff --git a/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.tsx b/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.tsx index fc5e2a24788..6bd6393075e 100644 --- a/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.tsx +++ b/frontend/packages/shared/src/components/altinnHeader/AltinnHeader.tsx @@ -5,7 +5,7 @@ import { AltinnSubMenu } from '../altinnSubHeader'; import { AltinnHeaderMenu } from '../altinnHeaderMenu'; import { AltinnHeaderButton } from '../altinnHeaderButtons/AltinnHeaderButton'; import { AltinnHeaderProfile } from '../AltinnHeaderProfile'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import classnames from 'classnames'; import { AltinnButtonActionItem, AltinnHeaderVariant } from './types'; import { Repository } from 'app-shared/types/Repository'; diff --git a/frontend/packages/shared/src/hooks/queries/useUserQuery.ts b/frontend/packages/shared/src/hooks/queries/useUserQuery.ts index 878f7259753..ff467684fe1 100644 --- a/frontend/packages/shared/src/hooks/queries/useUserQuery.ts +++ b/frontend/packages/shared/src/hooks/queries/useUserQuery.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryResult } from '@tanstack/react-query'; import { useServicesContext } from 'app-shared/contexts/ServicesContext'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { QueryKey } from 'app-shared/types/QueryKey'; export const useUserQuery = (): UseQueryResult => { diff --git a/frontend/packages/shared/src/mocks/mocks.ts b/frontend/packages/shared/src/mocks/mocks.ts index 0f47fa51664..722c9a09a5d 100644 --- a/frontend/packages/shared/src/mocks/mocks.ts +++ b/frontend/packages/shared/src/mocks/mocks.ts @@ -12,8 +12,8 @@ import { Commit } from 'app-shared/types/Commit'; import { OrgsState } from 'app-shared/types/OrgsState'; import { RepoStatus } from 'app-shared/types/RepoStatus'; import { RuleConfig } from 'app-shared/types/RuleConfig'; -import { IRepository, ITextResourcesWithLanguage } from 'app-shared/types/global'; -import { User } from 'app-shared/types/User'; +import { ITextResourcesWithLanguage } from 'app-shared/types/global'; +import { User } from 'app-shared/types/Repository'; import { AppConfig } from 'app-shared/types/AppConfig'; import { Policy } from '@altinn/policy-editor'; import { ApplicationMetadata } from 'app-shared/types/ApplicationMetadata'; @@ -121,13 +121,7 @@ export const user: User = { full_name: '', id: 1, login: '', -}; - -export const searchRepositoryResponse: SearchRepositoryResponse = { - data: [], - ok: false, - totalCount: 0, - totalPages: 0, + userType: 0, }; export const appConfig: AppConfig = { @@ -161,23 +155,6 @@ export const appLibVersion: AppLibVersion = { version: '', }; -export const customRepository: IRepository = { - name: '', - full_name: '', - owner: { - avatar_url: '', - login: '', - full_name: '', - }, - description: '', - is_cloned_to_local: false, - updated_at: '', - html_url: '', - clone_url: '', - id: 1, - user_has_starred: false, -}; - export const repository: Repository = { clone_url: '', created_at: '', @@ -188,7 +165,7 @@ export const repository: Repository = { forks_count: 0, full_name: '', html_url: '', - id: 0, + id: 1, is_cloned_to_local: false, mirror: false, name: '', @@ -199,7 +176,7 @@ export const repository: Repository = { full_name: '', id: 0, login: '', - UserType: 0, + userType: 0, }, permissions: { admin: false, @@ -232,3 +209,10 @@ export const resource: Resource = { identifier: '', title: {}, }; + +export const searchRepositoryResponse: SearchRepositoryResponse = { + data: [], + ok: false, + totalCount: 0, + totalPages: 0, +}; diff --git a/frontend/packages/shared/src/mocks/queriesMock.ts b/frontend/packages/shared/src/mocks/queriesMock.ts index b7f0ebd3e72..3600441b7cf 100644 --- a/frontend/packages/shared/src/mocks/queriesMock.ts +++ b/frontend/packages/shared/src/mocks/queriesMock.ts @@ -19,7 +19,7 @@ import { Validation, } from 'app-shared/types/ResourceAdm'; import { RuleConfig } from 'app-shared/types/RuleConfig'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { AppDeploymentsResponse, AppReleasesResponse, @@ -33,7 +33,6 @@ import { NewsList } from 'app-shared/types/api/NewsList'; import { IFrontEndSettings, ILayoutSettings, - IRepository, ITextResourcesObjectFormat, ITextResourcesWithLanguage, } from 'app-shared/types/global'; @@ -49,7 +48,6 @@ import { commit, createRepoCommitPayload, datamodelMetadataResponse, - customRepository, layoutSets, newsList, orgsState, @@ -106,7 +104,7 @@ export const queriesMock: ServicesContextProps = { getRepoStatus: jest.fn().mockImplementation(() => Promise.resolve(repoStatus)), getRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfig)), getRuleModel: jest.fn().mockImplementation(() => Promise.resolve('')), - getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve([])), + getStarredRepos: jest.fn().mockImplementation(() => Promise.resolve([])), getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve([])), getTextResources: jest .fn() @@ -153,7 +151,7 @@ export const queriesMock: ServicesContextProps = { addAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve()), addLanguageCode: jest.fn().mockImplementation(() => Promise.resolve()), addLayoutSet: jest.fn().mockImplementation(() => Promise.resolve()), - addRepo: jest.fn().mockImplementation(() => Promise.resolve(customRepository)), + addRepo: jest.fn().mockImplementation(() => Promise.resolve(repository)), addXsdFromRepo: jest.fn().mockImplementation(() => Promise.resolve({})), commitAndPushChanges: jest .fn() @@ -178,7 +176,7 @@ export const queriesMock: ServicesContextProps = { saveFormLayout: jest.fn().mockImplementation(() => Promise.resolve()), saveFormLayoutSettings: jest.fn().mockImplementation(() => Promise.resolve({})), saveRuleConfig: jest.fn().mockImplementation(() => Promise.resolve(ruleConfig)), - setStarredRepo: jest.fn().mockImplementation(() => Promise.resolve([])), + setStarredRepo: jest.fn().mockImplementation(() => Promise.resolve()), unsetStarredRepo: jest.fn().mockImplementation(() => Promise.resolve()), updateAppAttachmentMetadata: jest.fn().mockImplementation(() => Promise.resolve()), updateFormLayoutName: jest.fn().mockImplementation(() => Promise.resolve()), diff --git a/frontend/packages/shared/src/navigation/main-header/Header.test.tsx b/frontend/packages/shared/src/navigation/main-header/Header.test.tsx index 8d00814d7f5..87f51744d1b 100644 --- a/frontend/packages/shared/src/navigation/main-header/Header.test.tsx +++ b/frontend/packages/shared/src/navigation/main-header/Header.test.tsx @@ -1,18 +1,24 @@ import React from 'react'; import { render as rtlRender, screen } from '@testing-library/react'; -import Router from "react-router-dom"; +import Router from 'react-router-dom'; -import { getOrgNameByUsername, Header, HeaderContext, SelectedContextType } from './Header'; +import { + getOrgNameByUsername, + Header, + HeaderContext, + IHeaderContext, + SelectedContextType, +} from './Header'; const orgUsername = 'username1'; const orgFullName = 'Organization 1'; -jest.mock("react-router-dom", () => ({ - ...jest.requireActual("react-router-dom"), +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), useParams: jest.fn(), useNavigate: jest.fn(), - useLocation: jest.fn() + useLocation: jest.fn(), })); describe('Header', () => { @@ -45,13 +51,13 @@ describe('Header', () => { ...orgProps, id: 1, full_name: 'full_name 1', - username: 'username1' + username: 'username1', }, { ...orgProps, id: 2, full_name: 'full_name 2', - username: 'username2' + username: 'username2', }, ]; @@ -85,8 +91,10 @@ describe('Header', () => { const render = ({ selectedContext = SelectedContextType.Self, -}: {selectedContext: string | SelectedContextType}) => { - jest.spyOn(Router, 'useParams').mockReturnValue({ selectedContext }) +}: { + selectedContext: string | SelectedContextType; +}) => { + jest.spyOn(Router, 'useParams').mockReturnValue({ selectedContext }); const orgProps = { avatar_url: 'avatar_url', @@ -98,18 +106,21 @@ const render = ({ full_name: orgFullName, }; - const headerContextValue = { + const headerContextValue: IHeaderContext = { selectableOrgs: [{ ...orgProps }], user: { full_name: 'John Smith', avatar_url: 'avatar_url', login: 'login', + email: '', + id: 0, + userType: 0, }, }; return rtlRender(
- + , ); }; diff --git a/frontend/packages/shared/src/navigation/main-header/Header.tsx b/frontend/packages/shared/src/navigation/main-header/Header.tsx index f267de8e5b0..ff9e7eaa6dc 100644 --- a/frontend/packages/shared/src/navigation/main-header/Header.tsx +++ b/frontend/packages/shared/src/navigation/main-header/Header.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { AppBar, Grid, Toolbar, Typography } from '@mui/material'; -import type { IGiteaOrganisation, IUser } from '../../types/global'; +import type { IGiteaOrganisation } from '../../types/global'; +import type { User } from '../../types/Repository'; import AltinnStudioLogo from './AltinnStudioLogo'; import { HeaderMenu } from './HeaderMenu'; import classes from './Header.module.css'; @@ -13,7 +14,7 @@ export enum SelectedContextType { export interface IHeaderContext { selectableOrgs?: IGiteaOrganisation[]; - user: IUser; + user: User; } export const HeaderContext = React.createContext({ diff --git a/frontend/packages/shared/src/navigation/main-header/HeaderMenu.test.tsx b/frontend/packages/shared/src/navigation/main-header/HeaderMenu.test.tsx index 946f4990fb7..877eea19e7e 100644 --- a/frontend/packages/shared/src/navigation/main-header/HeaderMenu.test.tsx +++ b/frontend/packages/shared/src/navigation/main-header/HeaderMenu.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import * as networking from '../../utils/networking'; -import { HeaderContext, SelectedContextType } from './Header'; +import { HeaderContext, IHeaderContext, SelectedContextType } from './Header'; import type { HeaderMenuProps } from './HeaderMenu'; import { HeaderMenu } from './HeaderMenu'; import { act, render as rtlRender, screen } from '@testing-library/react'; @@ -13,11 +13,11 @@ jest.mock('../../utils/networking', () => ({ })); const mockedNavigate = jest.fn(); -jest.mock("react-router-dom", () => ({ - ...jest.requireActual("react-router-dom"), +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), useNavigate: () => mockedNavigate, useLocation: () => ({ - search: '' + search: '', }), })); @@ -99,7 +99,7 @@ const openMenu = async () => { const render = (props: Partial = {}) => { const handleSetSelectedContext = jest.fn(); - const headerContextValue = { + const headerContextValue: IHeaderContext = { selectableOrgs: [ { avatar_url: 'avatar_url', @@ -115,6 +115,9 @@ const render = (props: Partial = {}) => { full_name: 'John Smith', avatar_url: 'avatar_url', login: 'login', + email: '', + id: 0, + userType: 0, }, }; const allProps = { @@ -127,7 +130,7 @@ const render = (props: Partial = {}) => { rendered: rtlRender( - + , ), handleSetSelectedContext, }; diff --git a/frontend/packages/shared/src/navigation/main-header/ProfileMenu/ProfileMenu.tsx b/frontend/packages/shared/src/navigation/main-header/ProfileMenu/ProfileMenu.tsx index dfc58095a46..85e87e75283 100644 --- a/frontend/packages/shared/src/navigation/main-header/ProfileMenu/ProfileMenu.tsx +++ b/frontend/packages/shared/src/navigation/main-header/ProfileMenu/ProfileMenu.tsx @@ -5,7 +5,7 @@ import { altinnDocsUrl } from 'app-shared/ext-urls'; import { post } from '../../../utils/networking'; import { repositoryPath, userLogoutAfterPath, userLogoutPath } from '../../../api/paths'; import { useTranslation } from 'react-i18next'; -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; import { useStudioUrlParams } from 'app-shared/hooks/useStudioUrlParams'; import { Button } from '@digdir/design-system-react'; import * as testids from '../../../../../../testing/testids'; diff --git a/frontend/packages/shared/src/types/Repository.ts b/frontend/packages/shared/src/types/Repository.ts index af02dca3ee6..c0fc1994858 100644 --- a/frontend/packages/shared/src/types/Repository.ts +++ b/frontend/packages/shared/src/types/Repository.ts @@ -13,7 +13,7 @@ export interface Repository { mirror: boolean; name: string; open_issues_count: number; - owner: Owner; + owner: User; permissions: Permissions; private: boolean; repositoryCreatedStatus: number; @@ -25,13 +25,13 @@ export interface Repository { website: string; } -interface Owner { +export interface User { avatar_url: string; email: string; full_name: string; id: number; login: string; - UserType: number; + userType: number; } interface Permissions { diff --git a/frontend/packages/shared/src/types/User.ts b/frontend/packages/shared/src/types/User.ts deleted file mode 100644 index 3cf3f3bdb4a..00000000000 --- a/frontend/packages/shared/src/types/User.ts +++ /dev/null @@ -1,7 +0,0 @@ -export type User = { - avatar_url: string; - email: string; - full_name: string; - id: number; - login: string; -}; \ No newline at end of file diff --git a/frontend/packages/shared/src/types/api/SearchRepositoryResponse.ts b/frontend/packages/shared/src/types/api/SearchRepositoryResponse.ts index 3b0b0e7af8f..de147f55250 100644 --- a/frontend/packages/shared/src/types/api/SearchRepositoryResponse.ts +++ b/frontend/packages/shared/src/types/api/SearchRepositoryResponse.ts @@ -1,7 +1,7 @@ -import { IRepository } from 'app-shared/types/global'; +import { Repository } from 'app-shared/types/Repository'; export interface SearchRepositoryResponse { - data: IRepository[]; + data: Repository[]; ok: boolean; totalCount: number; totalPages: number; diff --git a/frontend/packages/shared/src/types/global.ts b/frontend/packages/shared/src/types/global.ts index 87de827b36e..1ae7eb47160 100644 --- a/frontend/packages/shared/src/types/global.ts +++ b/frontend/packages/shared/src/types/global.ts @@ -20,31 +20,12 @@ export interface IComponentsSettings { excludeFromPdf?: string[]; } -export interface IRepository { - name: string; - full_name: string; - owner: IUser; - description: string; - is_cloned_to_local: boolean; - updated_at: string; - html_url: string; - clone_url: string; - id: number; - user_has_starred: boolean; -} - export enum RepositoryType { App = 'App', Datamodels = 'Datamodels', Unknown = 'Unknown', } -export interface IUser { - avatar_url: string; - login: string; - full_name: string; -} - export interface IGiteaOrganisation { avatar_url: string; description?: string; From 22b386aeac8d789e42f9a4751820dfd3077b100d Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 22 Dec 2023 14:27:21 +0100 Subject: [PATCH 09/15] Add missing changes --- frontend/dashboard/pages/Dashboard/Dashboard.tsx | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/frontend/dashboard/pages/Dashboard/Dashboard.tsx b/frontend/dashboard/pages/Dashboard/Dashboard.tsx index 7aa1cc05c7e..1ec4de146d8 100644 --- a/frontend/dashboard/pages/Dashboard/Dashboard.tsx +++ b/frontend/dashboard/pages/Dashboard/Dashboard.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react'; import classes from './Dashboard.module.css'; -import { StudioPageSpinner } from '@studio/components'; import cn from 'classnames'; import type { ChangeEvent, KeyboardEvent } from 'react'; import { SearchField } from '@altinn/altinn-design-system'; @@ -17,7 +16,6 @@ import { useDebounce } from 'react-use'; import { useTranslation } from 'react-i18next'; import { User } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; -import { useStarredReposQuery } from '../../hooks/queries'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; import * as testids from '../../../testing/testids'; import { ResourcesRepoList } from 'dashboard/components/ResourcesRepoList/ResourcesRepoList'; @@ -32,7 +30,6 @@ type DashboardProps = { export const Dashboard = ({ user, organizations, disableDebounce }: DashboardProps) => { const { t } = useTranslation(); const selectedContext = useSelectedContext(); - const { data: starredRepos = [], isPending: areStarredReposPending } = useStarredReposQuery(); const [searchText, setSearchText] = useState(''); const [isNewLinkFocused, setIsNewLinkFocused] = useState(false); const [debouncedSearchText, setDebouncedSearchText] = useState(''); @@ -46,10 +43,6 @@ export const Dashboard = ({ user, organizations, disableDebounce }: DashboardPro const handleNewLinkFocus = () => setIsNewLinkFocused(true); const handleNewLinkFocusOut = () => setIsNewLinkFocused(false); - if (areStarredReposPending) { - return ; - } - return ( <> @@ -101,11 +94,7 @@ export const Dashboard = ({ user, organizations, disableDebounce }: DashboardPro
- + {selectedContext !== SelectedContextType.All && selectedContext !== SelectedContextType.Self && ( From e964580715df8eff5b106e70761ac0401bd9b0b1 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 22 Dec 2023 17:19:10 +0100 Subject: [PATCH 10/15] Fix missing properties --- .../DataModelsRepoList/DatamodelsRepoList.tsx | 16 +++++++- .../components/OrgRepoList/OrgReposList.tsx | 12 +++++- .../components/RepoList/RepoList.test.tsx | 41 +++++++++++++------ .../components/RepoList/RepoList.tsx | 31 +++++--------- .../SearchResultReposList.tsx | 12 +++++- .../hooks/queries/useStarredReposQuery.ts | 7 ++-- .../hooks/useAugmentReposWithStarred/index.ts | 1 + .../useAugmentReposWithStarred.ts | 13 ++++++ .../pages/Dashboard/Dashboard.test.tsx | 14 +------ frontend/dashboard/utils/repoUtils/index.ts | 3 +- .../dashboard/utils/repoUtils/repoUtils.ts | 25 +++++++++++ frontend/packages/shared/src/mocks/mocks.ts | 6 ++- 12 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts create mode 100644 frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts diff --git a/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx b/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx index 3801959b11c..f640ad548f0 100644 --- a/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx +++ b/frontend/dashboard/components/DataModelsRepoList/DatamodelsRepoList.tsx @@ -2,18 +2,21 @@ import React from 'react'; import { RepoList } from '../RepoList'; import { getReposLabel } from '../../utils/repoUtils'; import { getUidFilter } from '../../utils/filterUtils'; +import { useAugmentReposWithStarred } from '../../hooks/useAugmentReposWithStarred'; import { useTranslation } from 'react-i18next'; import { User } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; import { useSearchReposQuery } from 'dashboard/hooks/queries/useSearchReposQuery'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; import { Heading } from '@digdir/design-system-react'; +import { useStarredReposQuery } from 'dashboard/hooks/queries'; type DataModelsReposListProps = { user: User; organizations: Organization[]; }; export const DatamodelsReposList = ({ user, organizations }: DataModelsReposListProps) => { + const { data: starredRepos = [], isPending: areStarredReposPending } = useStarredReposQuery(); const selectedContext = useSelectedContext(); const { t } = useTranslation(); @@ -29,7 +32,12 @@ export const DatamodelsReposList = ({ user, organizations }: DataModelsReposList page: 0, }); - if (!repos?.data.length) { + const reposWithStarred = useAugmentReposWithStarred({ + repos: repos?.data, + starredRepos, + }); + + if (!reposWithStarred.length) { return null; } @@ -38,7 +46,11 @@ export const DatamodelsReposList = ({ user, organizations }: DataModelsReposList {getReposLabel({ selectedContext, orgs: organizations, t, isDatamodelsRepo: true })} - +
); }; diff --git a/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx b/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx index e3cb1be8ade..7d93ad1ae4e 100644 --- a/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx +++ b/frontend/dashboard/components/OrgRepoList/OrgReposList.tsx @@ -9,12 +9,15 @@ import { useReposSearch } from 'dashboard/hooks/useReposSearch'; import { useSelectedContext } from 'dashboard/hooks/useSelectedContext'; import { Heading } from '@digdir/design-system-react'; import { DATAGRID_DEFAULT_PAGE_SIZE } from 'dashboard/constants'; +import { useAugmentReposWithStarred } from 'dashboard/hooks/useAugmentReposWithStarred'; +import { useStarredReposQuery } from 'dashboard/hooks/queries'; type OrgReposListProps = { user: User; organizations: Organization[]; }; export const OrgReposList = ({ user, organizations }: OrgReposListProps) => { + const { data: starredRepos = [], isPending: areStarredReposPending } = useStarredReposQuery(); const selectedContext = useSelectedContext(); const { t } = useTranslation(); const uid = getUidFilter({ selectedContext, userId: user.id, organizations }); @@ -29,14 +32,19 @@ export const OrgReposList = ({ user, organizations }: OrgReposListProps) => { setPageSize, } = useReposSearch({ uid: uid as number, defaultPageSize: DATAGRID_DEFAULT_PAGE_SIZE }); + const reposWithStarred = useAugmentReposWithStarred({ + repos: searchResults?.data, + starredRepos, + }); + return (
{getReposLabel({ selectedContext, orgs: organizations, t })} !repo.name.endsWith('-datamodels'))} - isLoading={isLoadingSearchResults} + repos={reposWithStarred.filter((repo) => !repo.name.endsWith('-datamodels'))} + isLoading={isLoadingSearchResults || areStarredReposPending} onPageSizeChange={setPageSize} isServerSort={true} rowCount={searchResults?.totalCount ?? 0} diff --git a/frontend/dashboard/components/RepoList/RepoList.test.tsx b/frontend/dashboard/components/RepoList/RepoList.test.tsx index e8a5588636e..45ea5cbf978 100644 --- a/frontend/dashboard/components/RepoList/RepoList.test.tsx +++ b/frontend/dashboard/components/RepoList/RepoList.test.tsx @@ -3,7 +3,6 @@ import { act, screen, render, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MockServicesContextWrapper } from '../../dashboardTestUtils'; import { IRepoListProps, RepoList } from './RepoList'; -import type { Repository } from 'app-shared/types/Repository'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { textMock } from '../../../testing/mocks/i18nMock'; import { repository } from 'app-shared/mocks/mocks'; @@ -16,12 +15,28 @@ const renderWithMockServices = ( ) => { render( - + , ); }; describe('RepoList', () => { + test('should display spinner while loading starred repositories', () => { + renderWithMockServices({ + isLoading: true, + rowCount: 5, + }); + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + }); + + test('should display no repos when repos are empty', async () => { + renderWithMockServices({ + isLoading: false, + rowCount: 5, + }); + expect(await screen.findByText(textMock('dashboard.no_repos_result'))).toBeInTheDocument(); + }); + test('should not call onSortModelChange when clicking sort button and isServerSort is false', async () => { const handleSortMock = jest.fn(); renderWithMockServices({ @@ -56,17 +71,17 @@ describe('RepoList', () => { }); test('Should render GridActionsCellItem', async () => { - const getStarredRepos = jest - .fn() - .mockImplementation(() => Promise.resolve([repository])); - renderWithMockServices( - { - isLoading: false, - isServerSort: true, - rowCount: 5, - }, - { getStarredRepos }, - ); + renderWithMockServices({ + repos: [ + { + ...repository, + hasStarred: true, + }, + ], + isLoading: false, + isServerSort: true, + rowCount: 5, + }); const unstar = await screen.findByRole('menuitem', { name: textMock('dashboard.unstar') }); const gridActionsCellItem = within(unstar).getByRole('img'); expect(gridActionsCellItem).toBeInTheDocument(); diff --git a/frontend/dashboard/components/RepoList/RepoList.tsx b/frontend/dashboard/components/RepoList/RepoList.tsx index 66054b13aad..9121b7afff0 100644 --- a/frontend/dashboard/components/RepoList/RepoList.tsx +++ b/frontend/dashboard/components/RepoList/RepoList.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo, useRef, useState } from 'react'; +import React, { useMemo, useRef, useState } from 'react'; import type { GridActionsColDef, GridColDef, @@ -10,7 +10,7 @@ import type { } from '@mui/x-data-grid'; import { DataGrid, GridActionsCellItem, GridOverlay } from '@mui/x-data-grid'; import cn from 'classnames'; -import type { Repository } from 'app-shared/types/Repository'; +import type { RepositoryWithStarred } from 'dashboard/utils/repoUtils/repoUtils'; import { MakeCopyModal } from '../MakeCopyModal'; import { getRepoEditUrl } from '../../utils/urlUtils'; import { useTranslation } from 'react-i18next'; @@ -30,11 +30,10 @@ import { StarIcon, StarFillIcon, } from '@navikt/aksel-icons'; -import { useStarredReposQuery } from 'dashboard/hooks/queries'; export interface IRepoListProps { isLoading: boolean; - repos?: Repository[]; + repos?: RepositoryWithStarred[]; isServerSort?: boolean; pageSize?: DATAGRID_PAGE_SIZE_TYPE; rowCount: number; @@ -50,7 +49,7 @@ const defaultPageSizeOptions = DATAGRID_PAGE_SIZE_OPTIONS; const isRowSelectable = () => false; -const defaultArray: Repository[] = []; +const defaultArray: RepositoryWithStarred[] = []; const gridStyleOverride = { border: 'none', @@ -92,8 +91,6 @@ export const RepoList = ({ sortModel, disableVirtualization = false, }: IRepoListProps) => { - const { data: userStarredRepos, isPending: areUserStarredReposPending } = useStarredReposQuery(); - const [paginationModel, setPaginationModel] = React.useState({ pageSize, page: 0, @@ -116,11 +113,6 @@ export const RepoList = ({ const copyModalAnchorRef = useRef(null); const { t } = useTranslation(); - const isRepoStarred = useCallback( - (repoId: number) => userStarredRepos?.some((starredRepo) => starredRepo.id === repoId), - [userStarredRepos], - ); - const cols = useMemo(() => { const favouriteActionCol: GridActionsColDef = { field: '', @@ -130,11 +122,10 @@ export const RepoList = ({ headerClassName: classes.columnHeader, width: 50, getActions: (params: GridRowParams) => { - const repo = params.row as Repository; - const isStarred = isRepoStarred(repo.id); + const repo = params.row as RepositoryWithStarred; const handleToggleFav = () => { - if (isStarred) { + if (repo.hasStarred) { unsetStarredRepo(repo); } else { setStarredRepo(repo); @@ -146,9 +137,9 @@ export const RepoList = ({ key={repo.id} id={`fav-repo-${repo.id}`} onClick={handleToggleFav} - label={isStarred ? t('dashboard.unstar') : t('dashboard.star')} + label={repo.hasStarred ? t('dashboard.unstar') : t('dashboard.star')} icon={ - isStarred ? ( + repo.hasStarred ? ( ) : ( @@ -261,7 +252,7 @@ export const RepoList = ({ ]; return [favouriteActionCol, ...columns, ...actionsCol]; - }, [isRepoStarred, setStarredRepo, t, unsetStarredRepo]); + }, [setStarredRepo, t, unsetStarredRepo]); const handleCloseCopyModal = () => setCopyCurrentRepoName(null); @@ -285,7 +276,7 @@ export const RepoList = ({ }} componentsProps={componentPropsLabelOverrides} autoHeight={true} - loading={isLoading || areUserStarredReposPending} + loading={isLoading} rows={repos} columns={cols} disableColumnMenu={true} @@ -308,7 +299,7 @@ export const RepoList = ({ NoRowsOverlay: NoResults, }} autoHeight={true} - loading={isLoading || areUserStarredReposPending} + loading={isLoading} rows={repos} columns={cols} pageSizeOptions={pageSizeOptions} diff --git a/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx b/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx index 01f7cc24796..f630b325df8 100644 --- a/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx +++ b/frontend/dashboard/components/SearchResultReposList/SearchResultReposList.tsx @@ -1,12 +1,15 @@ import React from 'react'; +import { useAugmentReposWithStarred } from '../../hooks/useAugmentReposWithStarred'; import { RepoList } from '../RepoList'; import { useTranslation } from 'react-i18next'; import { useReposSearch } from 'dashboard/hooks/useReposSearch'; +import { useStarredReposQuery } from 'dashboard/hooks/queries'; type SearchResultReposList = { searchValue: string; }; export const SearchResultReposList = ({ searchValue }: SearchResultReposList) => { + const { data: starredRepos = [], isPending: areStarredReposPending } = useStarredReposQuery(); const { t } = useTranslation(); const { searchResults, @@ -18,12 +21,17 @@ export const SearchResultReposList = ({ searchValue }: SearchResultReposList) => setPageSize, } = useReposSearch({ keyword: searchValue }); + const reposWithStarred = useAugmentReposWithStarred({ + repos: searchResults?.data, + starredRepos, + }); + return (

{t('dashboard.search_result')}

=> { +export const useStarredReposQuery = (): UseQueryResult => { const { getStarredRepos } = useServicesContext(); return useQuery({ queryKey: [QueryKey.StarredRepos], - queryFn: () => getStarredRepos(), + queryFn: () => + getStarredRepos().then((data) => data.map((repo) => ({ ...repo, hasStarred: true }))), }); }; diff --git a/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts b/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts new file mode 100644 index 00000000000..2c75fe37b59 --- /dev/null +++ b/frontend/dashboard/hooks/useAugmentReposWithStarred/index.ts @@ -0,0 +1 @@ +export { useAugmentReposWithStarred } from './useAugmentReposWithStarred'; diff --git a/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts b/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts new file mode 100644 index 00000000000..a6561f4269f --- /dev/null +++ b/frontend/dashboard/hooks/useAugmentReposWithStarred/useAugmentReposWithStarred.ts @@ -0,0 +1,13 @@ +import { useMemo } from 'react'; +import type { MergeReposProps } from '../../utils/repoUtils'; +import { mergeRepos } from '../../utils/repoUtils'; +import { RepositoryWithStarred } from 'dashboard/utils/repoUtils/repoUtils'; + +export const useAugmentReposWithStarred = ({ + repos, + starredRepos, +}: MergeReposProps): RepositoryWithStarred[] => { + return useMemo(() => { + return mergeRepos({ repos, starredRepos }); + }, [repos, starredRepos]); +}; diff --git a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx index 16dfcf57a24..de12de9bf07 100644 --- a/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx +++ b/frontend/dashboard/pages/Dashboard/Dashboard.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, waitForElementToBeRemoved } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { MockServicesContextWrapper } from '../../dashboardTestUtils'; import { Dashboard } from './Dashboard'; import { textMock } from '../../../testing/mocks/i18nMock'; @@ -25,21 +25,10 @@ jest.mock('react-router-dom', () => ({ })); describe('Dashboard', () => { - test('should display spinner while loading starred repositories', () => { - renderWithMockServices(); - expect(screen.getByText(textMock('general.loading'))).toBeInTheDocument(); - }); - - test('should display no favorites when starred repos is empty', async () => { - renderWithMockServices(); - expect(await screen.findByText(textMock('dashboard.no_repos_result'))).toBeInTheDocument(); - }); - test('should display favorite list with one item', async () => { renderWithMockServices({ getStarredRepos: () => Promise.resolve([repository]), }); - await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); expect( await screen.findAllByRole('menuitem', { name: textMock('dashboard.unstar') }), ).toHaveLength(1); @@ -53,7 +42,6 @@ describe('Dashboard', () => { data: [repository], }), }); - await waitForElementToBeRemoved(() => screen.queryByText(textMock('general.loading'))); expect( await screen.findAllByRole('menuitem', { name: textMock('dashboard.star') }), ).toHaveLength(1); diff --git a/frontend/dashboard/utils/repoUtils/index.ts b/frontend/dashboard/utils/repoUtils/index.ts index c27e15c61b9..99c96ddb4a7 100644 --- a/frontend/dashboard/utils/repoUtils/index.ts +++ b/frontend/dashboard/utils/repoUtils/index.ts @@ -1 +1,2 @@ -export { getReposLabel, validateRepoName } from './repoUtils'; +export type { MergeReposProps } from './repoUtils'; +export { getReposLabel, mergeRepos, validateRepoName } from './repoUtils'; diff --git a/frontend/dashboard/utils/repoUtils/repoUtils.ts b/frontend/dashboard/utils/repoUtils/repoUtils.ts index 814299e510b..b8fc3f1a570 100644 --- a/frontend/dashboard/utils/repoUtils/repoUtils.ts +++ b/frontend/dashboard/utils/repoUtils/repoUtils.ts @@ -1,4 +1,5 @@ import { SelectedContextType } from 'app-shared/navigation/main-header/Header'; +import { Repository } from 'app-shared/types/Repository'; import { Organization } from 'app-shared/types/Organization'; import i18next from 'i18next'; @@ -10,6 +11,13 @@ type GetReposLabel = { isResourcesRepo?: boolean; }; +export type MergeReposProps = { + repos?: Repository[]; + starredRepos: Repository[]; +}; + +export type RepositoryWithStarred = Repository & { hasStarred?: boolean }; + type TranslationMapKey = SelectedContextType | 'named_org' | 'org'; type TranslationMap = Record; const appsTranslationMap: TranslationMap = { @@ -58,6 +66,23 @@ export const getReposLabel = ({ : t(concatenatedTranslationMap.org); }; +export const mergeRepos = ({ repos, starredRepos }: MergeReposProps): RepositoryWithStarred[] => { + if (!repos) { + return []; + } + + if (!starredRepos) { + return repos; + } + + return repos.map((repo) => { + return { + ...repo, + hasStarred: !!starredRepos.find((starredRepo) => starredRepo.id === repo.id), + }; + }); +}; + export const validateRepoName = (repoName: string) => { const appNameRegex = /^(?!datamodels$)[a-z][a-z0-9-]{1,28}[a-z0-9]$/; return appNameRegex.test(repoName); diff --git a/frontend/packages/shared/src/mocks/mocks.ts b/frontend/packages/shared/src/mocks/mocks.ts index 722c9a09a5d..e03331e8ded 100644 --- a/frontend/packages/shared/src/mocks/mocks.ts +++ b/frontend/packages/shared/src/mocks/mocks.ts @@ -207,7 +207,11 @@ export const organization: Organization = { export const resource: Resource = { identifier: '', - title: {}, + title: { + nb: '', + nn: '', + en: '', + }, }; export const searchRepositoryResponse: SearchRepositoryResponse = { From 894b2d544e43d579416ee27df35419f0ceb62b9f Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 22 Dec 2023 17:25:08 +0100 Subject: [PATCH 11/15] Fix date --- frontend/packages/shared/src/mocks/mocks.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/packages/shared/src/mocks/mocks.ts b/frontend/packages/shared/src/mocks/mocks.ts index e03331e8ded..445f202c2a4 100644 --- a/frontend/packages/shared/src/mocks/mocks.ts +++ b/frontend/packages/shared/src/mocks/mocks.ts @@ -88,8 +88,8 @@ export const orgsState: OrgsState = { export const commit: Commit = { message: '', - author: { name: '', email: '', when: new Date() }, - comitter: { name: '', email: '', when: new Date() }, + author: { name: '', email: '', when: new Date(null) }, + comitter: { name: '', email: '', when: new Date(null) }, sha: '', messageShort: '', encoding: '', From 905e030372d4e5bb54be0ba158df6a5db4438b70 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 2 Jan 2024 13:56:51 +0100 Subject: [PATCH 12/15] Fix typecheck errors --- frontend/app-development/test/userMock.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/app-development/test/userMock.ts b/frontend/app-development/test/userMock.ts index cac63092e47..b6cb294b8e1 100644 --- a/frontend/app-development/test/userMock.ts +++ b/frontend/app-development/test/userMock.ts @@ -1,4 +1,4 @@ -import { User } from 'app-shared/types/User'; +import { User } from 'app-shared/types/Repository'; export const userMock: User = { id: 1, @@ -6,4 +6,5 @@ export const userMock: User = { email: 'tester@tester.test', full_name: 'Tester Testersen', login: 'tester', + userType: 0, }; From 8bc21f6ae9ae4471d054c52b0309ba9731a9833b Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 2 Jan 2024 16:52:55 +0100 Subject: [PATCH 13/15] Cleanup tests --- .../overview/components/Overview.test.tsx | 44 ++++------- .../layout/PageLayout.test.tsx | 14 +--- .../SettingsModal/mocks/repositoryMock.ts | 32 +------- .../app-development/test/repositoryMock.ts | 77 ------------------- .../app-development/test/rootStateMock.ts | 4 +- .../MakeCopyModal/MakeCopyModal.test.tsx | 8 +- .../CreateService/CreateService.test.tsx | 70 +++++------------ .../VersionControlButtons.test.tsx | 12 +-- .../src/contexts/ServicesContext.test.tsx | 7 +- frontend/packages/shared/src/mocks/mocks.ts | 2 +- .../src/navigation/main-header/Header.tsx | 8 +- frontend/packages/shared/src/types/global.ts | 10 --- .../src/components/TextResource.test.tsx | 3 +- .../src/components/TextResourceEdit.test.tsx | 9 ++- .../editModal/EditDataModelBindings.test.tsx | 3 +- .../EditTextResourceBinding.test.tsx | 8 +- .../EditTextResourceBindings.test.tsx | 39 +++++++--- .../ResourceDashboardPage.test.tsx | 7 +- 18 files changed, 105 insertions(+), 252 deletions(-) delete mode 100644 frontend/app-development/test/repositoryMock.ts diff --git a/frontend/app-development/features/overview/components/Overview.test.tsx b/frontend/app-development/features/overview/components/Overview.test.tsx index b26e253054a..b96200c2d4a 100644 --- a/frontend/app-development/features/overview/components/Overview.test.tsx +++ b/frontend/app-development/features/overview/components/Overview.test.tsx @@ -4,7 +4,7 @@ import { Overview } from './Overview'; import { APP_DEVELOPMENT_BASENAME } from 'app-shared/constants'; import { renderWithProviders } from '../../../test/testUtils'; import { textMock } from '../../../../testing/mocks/i18nMock'; -import { privateRepositoryMock, repositoryMock } from '../../../test/repositoryMock'; +import { repository } from 'app-shared/mocks/mocks'; // Test data const org = 'org'; @@ -23,7 +23,6 @@ describe('Overview', () => { serviceName: title, }), ), - getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(repositoryMock)), }); expect(await screen.findByRole('heading', { name: title })).toBeInTheDocument(); @@ -54,27 +53,13 @@ describe('Overview', () => { }, }), ), - getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(repositoryMock)), - getDeployments: jest.fn().mockImplementation(() => + getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve({ - results: [ - { - tagName: '1', - envName: 'test', - deployedInEnv: true, - build: { - id: '1', - status: 'completed', - result: 'succeeded', - started: '2023-10-03T09:57:31.238Z', - finished: null, - }, - created: '2023-10-03T11:57:31.072013+02:00', - createdBy: 'test', - app, - org, - }, - ], + ...repository, + owner: { + ...repository.owner, + login: org, + }, }), ), }); @@ -85,7 +70,15 @@ describe('Overview', () => { it('should not display AppLogs if environments do not exist for repo owned by org', async () => { render({ - getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(repositoryMock)), + getRepoMetadata: jest.fn().mockImplementation(() => + Promise.resolve({ + ...repository, + owner: { + ...repository.owner, + login: org, + }, + }), + ), getOrgList: jest.fn().mockImplementation(() => Promise.resolve({ orgs: { @@ -95,7 +88,6 @@ describe('Overview', () => { }, }), ), - getEnvironments: jest.fn().mockImplementation(() => Promise.resolve([])), }); expect(await screen.findByText(textMock('app_publish.no_env_title'))).toBeInTheDocument(); expect( @@ -104,9 +96,7 @@ describe('Overview', () => { }); it('should display RepoOwnedByPersonInfo if repo is not owned by an org', async () => { - render({ - getRepoMetadata: jest.fn().mockImplementation(() => Promise.resolve(privateRepositoryMock)), - }); + render(); expect(await screen.findByText(textMock('app_publish.private_app_owner'))).toBeInTheDocument(); }); }); diff --git a/frontend/app-development/layout/PageLayout.test.tsx b/frontend/app-development/layout/PageLayout.test.tsx index 64ab267ef4e..1ea410fa0ef 100644 --- a/frontend/app-development/layout/PageLayout.test.tsx +++ b/frontend/app-development/layout/PageLayout.test.tsx @@ -7,13 +7,10 @@ import { textMock } from '../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; import { RoutePaths } from 'app-development/enums/RoutePaths'; import { repoStatus } from 'app-shared/mocks/mocks'; -import { privateRepositoryMock, repositoryMock } from '../test/repositoryMock'; const mockOrg: string = 'org'; const mockApp: string = 'app'; -const getRepoMetadata = jest.fn().mockImplementation(() => Promise.resolve(repositoryMock)); - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useParams: () => ({ @@ -68,9 +65,7 @@ describe('PageLayout', () => { }); it('renders header with no publish button when repoOwner is a private person', async () => { - await resolveAndWaitForSpinnerToDisappear({ - getRepoMetadata: () => Promise.resolve(privateRepositoryMock), - }); + await resolveAndWaitForSpinnerToDisappear(); expect(screen.getByRole('button', { name: textMock('top_menu.preview') })).toBeInTheDocument(); @@ -86,13 +81,8 @@ const resolveAndWaitForSpinnerToDisappear = async (queries: Partial = {}) => { - const allQueries: ServicesContextProps = { - getRepoMetadata, - ...queries, - }; - renderWithProviders(, { startUrl: `${APP_DEVELOPMENT_BASENAME}/my-org/my-app/${RoutePaths.Overview}`, - queries: allQueries, + queries, }); }; diff --git a/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts b/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts index e32e821dce6..313c4eb1e5d 100644 --- a/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts +++ b/frontend/app-development/layout/SettingsModalButton/SettingsModal/mocks/repositoryMock.ts @@ -1,41 +1,15 @@ +import { repository } from 'app-shared/mocks/mocks'; import { Repository } from 'app-shared/types/Repository'; export const mockRepository1: Repository = { - clone_url: '', + ...repository, created_at: '2023-09-20T10:40:00Z', - default_branch: '', - description: '', - empty: false, - fork: false, - forks_count: 0, - full_name: '', - html_url: '', - id: 123, - is_cloned_to_local: true, - mirror: false, name: 'CoolService', - open_issues_count: 0, owner: { - avatar_url: '', - email: '', + ...repository.owner, full_name: 'Mons Monsen', - id: 234, login: 'Mons', - userType: 2, }, - permissions: { - admin: true, - pull: true, - push: true, - }, - private: false, - repositoryCreatedStatus: 0, - size: 0, - ssh_url: '', - stars_count: 1337, - updated_at: '', - watchers_count: 0, - website: '', }; export const mockRepository2: Repository = { diff --git a/frontend/app-development/test/repositoryMock.ts b/frontend/app-development/test/repositoryMock.ts deleted file mode 100644 index 41967a7ed5b..00000000000 --- a/frontend/app-development/test/repositoryMock.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Repository } from 'app-shared/types/Repository'; - -export const repositoryMock: Repository = { - clone_url: '', - created_at: '', - default_branch: 'test', - description: '', - empty: false, - fork: false, - forks_count: 0, - full_name: 'app', - html_url: '', - id: 0, - is_cloned_to_local: false, - mirror: false, - name: 'test', - open_issues_count: 0, - owner: { - avatar_url: '', - email: '', - full_name: 'Testdepartementet', - id: 1, - login: 'org', - userType: 0, - }, - permissions: { - admin: true, - pull: true, - push: true, - }, - private: false, - repositoryCreatedStatus: 0, - size: 1, - ssh_url: '', - stars_count: 0, - updated_at: '', - watchers_count: 0, - website: '', -}; - -export const privateRepositoryMock: Repository = { - clone_url: '', - created_at: '', - default_branch: 'test', - description: '', - empty: false, - fork: false, - forks_count: 0, - full_name: 'privateApp', - html_url: '', - id: 1, - is_cloned_to_local: false, - mirror: false, - name: 'privateApp', - open_issues_count: 0, - owner: { - avatar_url: '', - email: 'tester@tester.test', - full_name: 'Tester Testersen', - id: 3, - login: 'tester', - userType: 0, - }, - permissions: { - admin: true, - pull: true, - push: true, - }, - private: false, - repositoryCreatedStatus: 0, - size: 1, - ssh_url: '', - stars_count: 0, - updated_at: '', - watchers_count: 0, - website: '', -}; diff --git a/frontend/app-development/test/rootStateMock.ts b/frontend/app-development/test/rootStateMock.ts index 35263d8350d..80bf985e16a 100644 --- a/frontend/app-development/test/rootStateMock.ts +++ b/frontend/app-development/test/rootStateMock.ts @@ -1,7 +1,7 @@ -import { repositoryMock } from './repositoryMock'; import { mockDeployments } from './appDeploymentsMock'; import type { RootState } from '../store'; import { applicationMetadataMock } from './applicationMetadataMock'; +import { repository } from 'app-shared/mocks/mocks'; export const rootStateMock: RootState = { applicationMetadataState: { @@ -9,7 +9,7 @@ export const rootStateMock: RootState = { error: null, }, serviceInformation: { - repositoryInfo: repositoryMock, + repositoryInfo: repository, error: null, initialCommit: null, serviceDescriptionObj: { diff --git a/frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx b/frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx index 73eb2d5ae17..295714f0e64 100644 --- a/frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx +++ b/frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx @@ -5,6 +5,7 @@ import { MakeCopyModal } from './MakeCopyModal'; import { MockServicesContextWrapper } from 'dashboard/dashboardTestUtils'; import { textMock } from '../../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; +import { queriesMock } from 'app-shared/mocks/queriesMock'; const user = userEvent.setup(); const org = 'org'; @@ -31,8 +32,7 @@ describe('MakeCopyModal', () => { }); test('should not show error message when clicking confirm and name is added', async () => { - const copyAppMock = jest.fn(() => Promise.resolve()); - renderWithMockServices({ copyApp: copyAppMock }); + renderWithMockServices(); await act(() => user.type(screen.getByRole('textbox'), 'new-repo-name')); await act(() => @@ -44,8 +44,8 @@ describe('MakeCopyModal', () => { ); expect(screen.queryByText(textMock('dashboard.field_cannot_be_empty'))).not.toBeInTheDocument(); - expect(copyAppMock).toHaveBeenCalledTimes(1); - expect(copyAppMock).toHaveBeenCalledWith('org', 'app', 'new-repo-name'); + expect(queriesMock.copyApp).toHaveBeenCalledTimes(1); + expect(queriesMock.copyApp).toHaveBeenCalledWith('org', 'app', 'new-repo-name'); }); test('should show error message when clicking confirm without adding name', async () => { diff --git a/frontend/dashboard/pages/CreateService/CreateService.test.tsx b/frontend/dashboard/pages/CreateService/CreateService.test.tsx index 69bb3a28e61..6e14e39026f 100644 --- a/frontend/dashboard/pages/CreateService/CreateService.test.tsx +++ b/frontend/dashboard/pages/CreateService/CreateService.test.tsx @@ -3,61 +3,19 @@ import { act, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MockServicesContextWrapper } from '../../dashboardTestUtils'; import { CreateService } from './CreateService'; -import { Repository, User } from 'app-shared/types/Repository'; -import { IGiteaOrganisation } from 'app-shared/types/global'; +import { User } from 'app-shared/types/Repository'; +import { Organization } from 'app-shared/types/Organization'; import { textMock } from '../../../testing/mocks/i18nMock'; import { ServicesContextProps } from 'app-shared/contexts/ServicesContext'; +import { repository, user as userMock } from 'app-shared/mocks/mocks'; -const orgMock: IGiteaOrganisation = { +const orgMock: Organization = { avatar_url: '', id: 1, username: 'unit-test', full_name: 'unit-test', }; -const repositoryMock: Repository = { - clone_url: '', - description: '', - full_name: 'test', - html_url: '', - id: 0, - is_cloned_to_local: false, - name: 'test', - owner: { - avatar_url: '', - full_name: '', - login: '', - email: '', - id: 0, - userType: 0, - }, - updated_at: '', - created_at: '', - default_branch: '', - empty: false, - fork: false, - forks_count: 0, - mirror: false, - open_issues_count: 0, - permissions: undefined, - private: false, - repositoryCreatedStatus: 0, - size: 0, - ssh_url: '', - stars_count: 0, - watchers_count: 0, - website: '', -}; - -const userMock: User = { - id: 1, - avatar_url: '', - email: 'tester@tester.test', - full_name: 'Tester Testersen', - login: 'tester', - userType: 0, -}; - jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn(), @@ -65,7 +23,7 @@ jest.mock('react-router-dom', () => ({ const renderWithMockServices = ( services?: Partial, - organizations?: IGiteaOrganisation[], + organizations?: Organization[], user?: User, ) => { render( @@ -219,12 +177,19 @@ describe('CreateService', () => { addRepo: () => new Promise((resolve) => setTimeout(() => { - resolve(repositoryMock); + resolve({ + ...repository, + full_name: 'test', + name: 'test', + }); }, 2), ), }, [orgMock], - userMock, + { + ...userMock, + login: 'tester', + }, ); const createBtn: HTMLElement = screen.getByRole('button', { @@ -271,10 +236,13 @@ describe('CreateService', () => { renderWithMockServices( { - addRepo: () => Promise.resolve(repositoryMock), + addRepo: () => Promise.resolve(repository), }, [orgMock], - userMock, + { + ...userMock, + login: 'tester', + }, ); const createBtn: HTMLElement = screen.getByRole('button', { diff --git a/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx b/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx index 2094e0096f6..15abf1375da 100644 --- a/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx +++ b/frontend/packages/shared/src/components/GiteaHeader/VersionControlButtons/VersionControlButtons.test.tsx @@ -9,6 +9,7 @@ import type { RepoStatus } from 'app-shared/types/RepoStatus'; import { queryClientMock } from 'app-shared/mocks/queryClientMock'; import * as testids from '../../../../../../testing/testids'; import { queriesMock } from 'app-shared/mocks/queriesMock'; +import { repoStatus } from 'app-shared/mocks/mocks'; const user = userEvent.setup(); const org = 'test-org'; @@ -29,25 +30,20 @@ jest.mock('react-router-dom', () => ({ * for instance the `renderWithProviders` method. */ const okRepoStatus: RepoStatus = { - aheadBy: 0, - behindBy: 0, - contentStatus: [], - hasMergeConflict: false, + ...repoStatus, repositoryStatus: 'Ok', }; const aheadRepoStatus: RepoStatus = { + ...repoStatus, aheadBy: 1, - behindBy: 0, - contentStatus: [], - hasMergeConflict: false, repositoryStatus: 'Ok', }; const mergeConflictRepoStatus: RepoStatus = { + ...repoStatus, aheadBy: 1, behindBy: 1, - contentStatus: [], hasMergeConflict: true, repositoryStatus: 'CheckoutConflict', }; diff --git a/frontend/packages/shared/src/contexts/ServicesContext.test.tsx b/frontend/packages/shared/src/contexts/ServicesContext.test.tsx index 8739d4c0316..639e8decae9 100644 --- a/frontend/packages/shared/src/contexts/ServicesContext.test.tsx +++ b/frontend/packages/shared/src/contexts/ServicesContext.test.tsx @@ -27,7 +27,7 @@ const wrapper = ({ queries = {}, }: { children: React.JSX.Element; - queries: Partial; + queries?: Partial; }) => { const allQueries: ServicesContextProps = { ...queriesMock, @@ -40,7 +40,6 @@ describe('ServicesContext', () => { it('logs the user out after displaying a toast for a given time when the api says unauthorized', async () => { const mockConsoleError = jest.spyOn(console, 'error').mockImplementation(); jest.spyOn(global, 'setTimeout'); - const logout = jest.fn().mockImplementation(() => Promise.resolve()); renderHook( () => useQuery({ @@ -50,14 +49,14 @@ describe('ServicesContext', () => { }), { wrapper: ({ children }) => { - return wrapper({ children, queries: { logout } }); + return wrapper({ children }); }, }, ); expect(await screen.findByText(textMock('api_errors.Unauthorized'))).toBeInTheDocument(); jest.runAllTimers(); await waitFor(() => { - expect(logout).toHaveBeenCalledTimes(1); + expect(queriesMock.logout).toHaveBeenCalledTimes(1); }); expect(mockConsoleError).toHaveBeenCalled(); diff --git a/frontend/packages/shared/src/mocks/mocks.ts b/frontend/packages/shared/src/mocks/mocks.ts index 445f202c2a4..12908a76405 100644 --- a/frontend/packages/shared/src/mocks/mocks.ts +++ b/frontend/packages/shared/src/mocks/mocks.ts @@ -174,7 +174,7 @@ export const repository: Repository = { avatar_url: '', email: '', full_name: '', - id: 0, + id: 1, login: '', userType: 0, }, diff --git a/frontend/packages/shared/src/navigation/main-header/Header.tsx b/frontend/packages/shared/src/navigation/main-header/Header.tsx index ff9e7eaa6dc..42ede8016dd 100644 --- a/frontend/packages/shared/src/navigation/main-header/Header.tsx +++ b/frontend/packages/shared/src/navigation/main-header/Header.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { AppBar, Grid, Toolbar, Typography } from '@mui/material'; -import type { IGiteaOrganisation } from '../../types/global'; +import type { Organization } from '../../types/Organization'; import type { User } from '../../types/Repository'; import AltinnStudioLogo from './AltinnStudioLogo'; import { HeaderMenu } from './HeaderMenu'; @@ -13,7 +13,7 @@ export enum SelectedContextType { } export interface IHeaderContext { - selectableOrgs?: IGiteaOrganisation[]; + selectableOrgs?: Organization[]; user: User; } @@ -22,12 +22,12 @@ export const HeaderContext = React.createContext({ user: undefined, }); -export const getOrgNameByUsername = (username: string, orgs: IGiteaOrganisation[]) => { +export const getOrgNameByUsername = (username: string, orgs: Organization[]) => { const org = orgs?.find((o) => o.username === username); return org?.full_name || org?.username; }; -export const getOrgUsernameByUsername = (username: string, orgs: IGiteaOrganisation[]) => { +export const getOrgUsernameByUsername = (username: string, orgs: Organization[]) => { const org = orgs?.find((o) => o.username === username); return org?.username; }; diff --git a/frontend/packages/shared/src/types/global.ts b/frontend/packages/shared/src/types/global.ts index 1ae7eb47160..adf1089d678 100644 --- a/frontend/packages/shared/src/types/global.ts +++ b/frontend/packages/shared/src/types/global.ts @@ -26,16 +26,6 @@ export enum RepositoryType { Unknown = 'Unknown', } -export interface IGiteaOrganisation { - avatar_url: string; - description?: string; - id: number; - location?: string; - username: string; - website?: string; - full_name?: string; -} - export interface IContentStatus { filePath: string; fileStatus: string; diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index 37aa8b1160a..9b7bf7f4c4d 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -250,7 +250,6 @@ const renderAndOpenSearchSection = async () => { }; const waitForData = async (resources: ITextResource[]) => { - const getTextLanguages = jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)); const { result } = renderHookWithMockStore( {}, { @@ -260,7 +259,7 @@ const waitForData = async (resources: ITextResource[]) => { resources, }), ), - getTextLanguages, + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), }, )(() => useTextResourcesQuery(org, app)).renderHookResult; const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) diff --git a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx index 35fda2dfb00..beb98dccb10 100644 --- a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx @@ -5,7 +5,12 @@ import type { ITextResources, ITextResourcesWithLanguage } from 'app-shared/type import userEvent from '@testing-library/user-event'; import { TextResourceEdit } from './TextResourceEdit'; import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { renderHookWithMockStore, renderWithMockStore, queryClientMock } from '../testing/mocks'; +import { + renderHookWithMockStore, + renderWithMockStore, + queryClientMock, + textLanguagesMock, +} from '../testing/mocks'; import { appDataMock, textResourcesMock } from '../testing/stateMocks'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import { mockUseTranslation } from '../../../../testing/mocks/i18nMock'; @@ -174,7 +179,7 @@ const render = async ( const { result } = renderHookWithMockStore( { appData }, { - getTextLanguages: () => Promise.resolve(['nb', 'nn', 'en']), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), getTextResources: (_o, _a, lang) => Promise.resolve({ language: lang, diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx index 980a32edfbb..7c1efc4c4bb 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx @@ -7,8 +7,9 @@ import { EditDataModelBindings } from './EditDataModelBindings'; import { textMock } from '../../../../../../testing/mocks/i18nMock'; import { ComponentType } from 'app-shared/types/ComponentType'; import userEvent from '@testing-library/user-event'; +import { DatamodelMetadataResponse } from 'app-shared/types/api'; -const datamodelMetadata = { +const datamodelMetadata: DatamodelMetadataResponse = { elements: { testModel: { id: 'testModel', diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx index 3db4fedbc59..75d5c8dc6ee 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBinding.test.tsx @@ -2,7 +2,11 @@ import React from 'react'; import { EditTextResourceBinding, EditTextResourceBindingProps } from './EditTextResourceBinding'; import { act, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../testing/mocks'; +import { + renderHookWithMockStore, + renderWithMockStore, + textLanguagesMock, +} from '../../../testing/mocks'; import { useLayoutSchemaQuery } from '../../../hooks/queries/useLayoutSchemaQuery'; import type { ITextResource } from 'app-shared/types/global'; import { textMock } from '../../../../../../testing/mocks/i18nMock'; @@ -110,7 +114,7 @@ describe('EditTextResourceBindings component', () => { const { result } = renderHookWithMockStore( {}, { - getTextLanguages: () => Promise.resolve(['nb', 'nn', 'en']), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), getTextResources: (_o, _a, lang) => Promise.resolve({ language: lang, diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBindings.test.tsx index 9e64180e6ac..8ec41768305 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditTextResourceBindings.test.tsx @@ -4,7 +4,11 @@ import { EditTextResourceBindingsProps, } from './EditTextResourceBindings'; import { act, screen, waitFor } from '@testing-library/react'; -import { renderHookWithMockStore, renderWithMockStore } from '../../../testing/mocks'; +import { + renderHookWithMockStore, + renderWithMockStore, + textLanguagesMock, +} from '../../../testing/mocks'; import { useLayoutSchemaQuery } from '../../../hooks/queries/useLayoutSchemaQuery'; import type { ITextResource } from 'app-shared/types/global'; import { textMock } from '../../../../../../testing/mocks/i18nMock'; @@ -39,15 +43,21 @@ describe('EditTextResourceBindings component', () => { test('that it renders with expected text resource binding keys', async () => { const textResourceBindingKeys = ['title', 'description', 'help']; await renderEditTextResourceBindingsComponent({ textResourceBindingKeys }); - const label = screen.getByText(textMock(`ux_editor.modal_properties_textResourceBindings_test`)); + const label = screen.getByText( + textMock(`ux_editor.modal_properties_textResourceBindings_test`), + ); const text = screen.getByText('This is a test'); expect(label).toBeInTheDocument(); expect(text).toBeInTheDocument(); }); test('that it renders no text resource bindings if none are added', async () => { - await renderEditTextResourceBindingsComponent({ component: { ...mockComponent, textResourceBindings: {} } }); - const titleLabel = screen.queryByText(textMock(`ux_editor.modal_properties_textResourceBindings_title`)); + await renderEditTextResourceBindingsComponent({ + component: { ...mockComponent, textResourceBindings: {} }, + }); + const titleLabel = screen.queryByText( + textMock(`ux_editor.modal_properties_textResourceBindings_title`), + ); expect(titleLabel).not.toBeInTheDocument(); const searchTextButton = screen.queryByRole('button', { name: textMock('general.search') }); expect(searchTextButton).not.toBeInTheDocument(); @@ -56,14 +66,18 @@ describe('EditTextResourceBindings component', () => { test('that it renders the combobox for selecting text resource binding keys to add', async () => { const textResourceBindingKeys = ['title', 'description', 'help']; await renderEditTextResourceBindingsComponent({ textResourceBindingKeys }); - const selectTextResourcesCombobox = screen.getByRole('combobox', { name: textMock('ux_editor.text_resource_bindings.add_label') }); + const selectTextResourcesCombobox = screen.getByRole('combobox', { + name: textMock('ux_editor.text_resource_bindings.add_label'), + }); expect(selectTextResourcesCombobox).toBeInTheDocument(); }); test('that the combobox for selecting text resource binding keys only contains keys that are not already added', async () => { const textResourceBindingKeys = ['title', 'description', 'help']; await renderEditTextResourceBindingsComponent({ textResourceBindingKeys }); - const selectTextResourcesCombobox = screen.getByRole('combobox', { name: textMock('ux_editor.text_resource_bindings.add_label') }); + const selectTextResourcesCombobox = screen.getByRole('combobox', { + name: textMock('ux_editor.text_resource_bindings.add_label'), + }); await act(() => userEvent.click(selectTextResourcesCombobox)); // eslint-disable-line testing-library/no-unnecessary-act let options = screen.getAllByRole('option'); @@ -78,24 +92,27 @@ describe('EditTextResourceBindings component', () => { test('that it does not render the combobox for selecting text resource binding keys when all available keys are added', async () => { const textResourceBindingKeys = ['test']; await renderEditTextResourceBindingsComponent({ textResourceBindingKeys }); - const selectTextResourcesCombobox = screen.queryByRole('combobox', { name: textMock('ux_editor.text_resource_bindings.add_label') }); + const selectTextResourcesCombobox = screen.queryByRole('combobox', { + name: textMock('ux_editor.text_resource_bindings.add_label'), + }); const addTextResourceButton = screen.queryByRole('button', { name: textMock('general.add') }); expect(selectTextResourcesCombobox).not.toBeInTheDocument(); expect(addTextResourceButton).not.toBeInTheDocument(); }); const waitForData = async () => { - const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()).renderHookResult.result; + const layoutSchemaResult = renderHookWithMockStore()(() => useLayoutSchemaQuery()) + .renderHookResult.result; const { result } = renderHookWithMockStore( {}, { - getTextLanguages: () => Promise.resolve(['nb', 'nn', 'en']), + getTextLanguages: jest.fn().mockImplementation(() => Promise.resolve(textLanguagesMock)), getTextResources: (_o, _a, lang) => Promise.resolve({ language: lang, resources: textResources, }), - } + }, )(() => useTextResourcesQuery(org, app)).renderHookResult; await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true)); await waitFor(() => expect(result.current.isSuccess).toBe(true)); @@ -113,7 +130,7 @@ describe('EditTextResourceBindings component', () => { component={component} handleComponentChange={handleComponentChange} textResourceBindingKeys={textResourceBindingKeys} - /> + />, ); }; }); diff --git a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx index d579b137761..b427c4fc214 100644 --- a/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx +++ b/frontend/resourceadm/pages/ResourceDashboardPage/ResourceDashboardPage.test.tsx @@ -11,6 +11,7 @@ import { ServicesContextProps, ServicesContextProvider } from 'app-shared/contex import { QueryClient } from '@tanstack/react-query'; import { queriesMock } from 'app-shared/mocks/queriesMock'; import { Organization } from 'app-shared/types/Organization'; +import { organization } from 'app-shared/mocks/mocks'; const mockResourceListItem1: ResourceListItem = { title: { nb: 'resource 1', nn: '', en: '' }, @@ -75,13 +76,9 @@ describe('ResourceDashBoardPage', () => { const getOrganizations = jest.fn().mockImplementation(() => Promise.resolve([ { - avatar_url: 'http://studio.localhost/repos/avatars/5d076e5c3d34cb8bb08e54a4bb7e223e', - description: 'Internt organisasjon for test av løsning', + ...organization, full_name: 'Testdepartementet', - id: 3, - location: '', username: 'ttd', - website: '', }, ]), ); From 414d8bde871c7e30ad9d6a64f46e7c82c8c6a9ab Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 10 Jan 2024 15:57:44 +0100 Subject: [PATCH 14/15] Fix EditDataModelBindings tests --- .../components/config/editModal/EditDataModelBindings.test.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx index 037b4f158ba..b9171f9013d 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx @@ -131,8 +131,7 @@ describe('EditDataModelBindings', () => { await render({ handleComponentChange }); const linkIcon = screen.getByText(textMock('ux_editor.modal_properties_data_model_link')); await act(() => user.click(linkIcon)); - const select = screen.getByRole('combobox'); - const option = within(select).getByText(''); + const option = screen.getByText('testModel'); await act(() => user.click(option)); expect(handleComponentChange).toHaveBeenCalledWith({ dataModelBindings: { simpleBinding: 'testModel' }, From 747450ac29e3db1ce786e7df762c0b9cce63f7af Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 10 Jan 2024 17:12:59 +0100 Subject: [PATCH 15/15] Remove duplicated queryClientMock --- .../src/components/AppPreviewSubMenu.test.tsx | 6 ++---- .../Elements/LayoutSetsContainer.test.tsx | 12 ++++-------- .../src/components/Preview/Preview.test.tsx | 13 +++++++------ .../ux-editor/src/components/TextResource.test.tsx | 8 ++------ .../src/components/TextResourceEdit.test.tsx | 8 ++------ .../config/editModal/EditDataModelBindings.test.tsx | 2 +- .../mutations/useAddItemToLayoutMutation.test.ts | 3 ++- .../hooks/mutations/useDeleteLayoutMutation.test.ts | 7 ++----- .../hooks/mutations/useFormLayoutMutation.test.tsx | 3 ++- .../useUpdateFormComponentMutation.test.ts | 3 ++- 10 files changed, 26 insertions(+), 39 deletions(-) diff --git a/frontend/app-preview/src/components/AppPreviewSubMenu.test.tsx b/frontend/app-preview/src/components/AppPreviewSubMenu.test.tsx index 1698c74c4ce..de1dcd09428 100644 --- a/frontend/app-preview/src/components/AppPreviewSubMenu.test.tsx +++ b/frontend/app-preview/src/components/AppPreviewSubMenu.test.tsx @@ -1,8 +1,6 @@ import React from 'react'; -import { - queryClientMock, - renderWithMockStore -} from '../../../../frontend/packages/ux-editor/src/testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderWithMockStore } from '../../../../frontend/packages/ux-editor/src/testing/mocks'; import { layoutSetsMock } from '../../../../frontend/packages/ux-editor/src/testing/layoutMock'; import { AppPreviewSubMenuProps, AppPreviewSubMenu } from './AppPreviewSubMenu'; import { LayoutSets } from 'app-shared/types/api/LayoutSetsResponse'; diff --git a/frontend/packages/ux-editor/src/components/Elements/LayoutSetsContainer.test.tsx b/frontend/packages/ux-editor/src/components/Elements/LayoutSetsContainer.test.tsx index 0d5d42f318b..7d656f6cb24 100644 --- a/frontend/packages/ux-editor/src/components/Elements/LayoutSetsContainer.test.tsx +++ b/frontend/packages/ux-editor/src/components/Elements/LayoutSetsContainer.test.tsx @@ -2,7 +2,8 @@ import React from 'react'; import { act, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { LayoutSetsContainer } from './LayoutSetsContainer'; -import { queryClientMock, renderWithMockStore } from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderWithMockStore } from '../../testing/mocks'; import { layoutSetsMock } from '../../testing/layoutMock'; import { AppContextProps } from '../../AppContext'; import { appStateMock } from '../../testing/stateMocks'; @@ -24,12 +25,8 @@ describe('LayoutSetsContainer', () => { it('renders component', async () => { render(); - expect( - await screen.findByRole('option', { name: layoutSetName1 }), - ).toBeInTheDocument(); - expect( - await screen.findByRole('option', { name: layoutSetName2 }), - ).toBeInTheDocument(); + expect(await screen.findByRole('option', { name: layoutSetName1 })).toBeInTheDocument(); + expect(await screen.findByRole('option', { name: layoutSetName2 })).toBeInTheDocument(); }); it('NativeSelect should be rendered', async () => { @@ -43,7 +40,6 @@ describe('LayoutSetsContainer', () => { await act(() => user.selectOptions(screen.getByRole('combobox'), layoutSetName2)); expect(setSelectedLayoutSetMock).toHaveBeenCalledTimes(1); }); - }); const render = () => { diff --git a/frontend/packages/ux-editor/src/components/Preview/Preview.test.tsx b/frontend/packages/ux-editor/src/components/Preview/Preview.test.tsx index 9f6a142f8b7..253c30adb2c 100644 --- a/frontend/packages/ux-editor/src/components/Preview/Preview.test.tsx +++ b/frontend/packages/ux-editor/src/components/Preview/Preview.test.tsx @@ -1,7 +1,8 @@ import React, { createRef } from 'react'; import { Preview } from './Preview'; import { act, screen } from '@testing-library/react'; -import { queryClientMock, renderWithMockStore } from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderWithMockStore } from '../../testing/mocks'; import type { IAppState } from '../../types/global'; import { textMock } from '../../../../../testing/mocks/i18nMock'; import userEvent from '@testing-library/user-event'; @@ -9,14 +10,14 @@ import userEvent from '@testing-library/user-event'; describe('Preview', () => { it('Renders an iframe with the ref from AppContext', () => { const previewIframeRef = createRef(); - renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); + renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); expect(screen.getByTitle(textMock('ux_editor.preview'))).toBe(previewIframeRef.current); }); it('should be able to toggle between mobile and desktop view', async () => { const user = userEvent.setup(); const previewIframeRef = createRef(); - renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); + renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); const switchButton = screen.getByRole('checkbox', { name: textMock('ux_editor.mobilePreview'), @@ -30,15 +31,15 @@ describe('Preview', () => { it('should render a message when no page is selected', () => { const mockedLayout = { layout: { selectedLayout: undefined } } as IAppState['formDesigner']; - renderWithMockStore({ formDesigner: mockedLayout }, {}, queryClientMock)(); + renderWithMockStore({ formDesigner: mockedLayout }, {}, queryClientMock)(); expect(screen.getByText(textMock('ux_editor.no_components_selected'))).toBeInTheDocument(); }); it('Renders the information alert with preview being limited', () => { const previewIframeRef = createRef(); - renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); + renderWithMockStore({}, {}, queryClientMock, { previewIframeRef })(); const previewLimitationsAlert = screen.getByText(textMock('preview.limitations_info')); expect(previewLimitationsAlert).toBeInTheDocument(); }); -}); \ No newline at end of file +}); diff --git a/frontend/packages/ux-editor/src/components/TextResource.test.tsx b/frontend/packages/ux-editor/src/components/TextResource.test.tsx index 9b7bf7f4c4d..941da9224aa 100644 --- a/frontend/packages/ux-editor/src/components/TextResource.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResource.test.tsx @@ -1,13 +1,9 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import type { ITextResource, ITextResourcesWithLanguage } from 'app-shared/types/global'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; import { TextResource, TextResourceProps } from './TextResource'; -import { - queryClientMock, - renderHookWithMockStore, - renderWithMockStore, - textLanguagesMock, -} from '../testing/mocks'; +import { renderHookWithMockStore, renderWithMockStore, textLanguagesMock } from '../testing/mocks'; import { useLayoutSchemaQuery } from '../hooks/queries/useLayoutSchemaQuery'; import { act, screen, waitFor } from '@testing-library/react'; import { textMock } from '../../../../testing/mocks/i18nMock'; diff --git a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx index beb98dccb10..9e2c8b9dcca 100644 --- a/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx +++ b/frontend/packages/ux-editor/src/components/TextResourceEdit.test.tsx @@ -5,12 +5,8 @@ import type { ITextResources, ITextResourcesWithLanguage } from 'app-shared/type import userEvent from '@testing-library/user-event'; import { TextResourceEdit } from './TextResourceEdit'; import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { - renderHookWithMockStore, - renderWithMockStore, - queryClientMock, - textLanguagesMock, -} from '../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderHookWithMockStore, renderWithMockStore, textLanguagesMock } from '../testing/mocks'; import { appDataMock, textResourcesMock } from '../testing/stateMocks'; import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import { mockUseTranslation } from '../../../../testing/mocks/i18nMock'; diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx index b9171f9013d..97e32beba13 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditDataModelBindings.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { act, screen, within } from '@testing-library/react'; +import { act, screen } from '@testing-library/react'; import { renderWithMockStore } from '../../../testing/mocks'; import { appDataMock, textResourcesMock } from '../../../testing/stateMocks'; import { IAppDataState } from '../../../features/appData/appDataReducers'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts index 634b88118b5..6c6c1335af3 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useAddItemToLayoutMutation.test.ts @@ -1,5 +1,6 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { appStateMock, formDesignerMock } from '../../testing/stateMocks'; import { waitFor } from '@testing-library/react'; import { AddFormItemMutationArgs, useAddItemToLayoutMutation } from './useAddItemToLayoutMutation'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts index 3b1b2b5bf89..32b84fe2546 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useDeleteLayoutMutation.test.ts @@ -1,9 +1,6 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { - formLayoutSettingsMock, - renderHookWithMockStore, - queryClientMock, -} from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { formLayoutSettingsMock, renderHookWithMockStore } from '../../testing/mocks'; import { useDeleteLayoutMutation } from './useDeleteLayoutMutation'; import { externalLayoutsMock, layout2NameMock } from '../../testing/layoutMock'; import { QueryKey } from 'app-shared/types/QueryKey'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx index 0d56fff6918..4702ca3a6de 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx +++ b/frontend/packages/ux-editor/src/hooks/mutations/useFormLayoutMutation.test.tsx @@ -1,5 +1,6 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { useFormLayoutMutation } from './useFormLayoutMutation'; import { IInternalLayout } from '../../types/global'; import { ComponentType } from 'app-shared/types/ComponentType'; diff --git a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts index 4a38a146f65..f68513d7647 100644 --- a/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts +++ b/frontend/packages/ux-editor/src/hooks/mutations/useUpdateFormComponentMutation.test.ts @@ -1,5 +1,6 @@ import { queriesMock } from 'app-shared/mocks/queriesMock'; -import { queryClientMock, renderHookWithMockStore } from '../../testing/mocks'; +import { queryClientMock } from 'app-shared/mocks/queryClientMock'; +import { renderHookWithMockStore } from '../../testing/mocks'; import { ComponentType } from 'app-shared/types/ComponentType'; import { UpdateFormComponentMutationArgs,