From e1cf07dce0f78d472bd384498e5a8c480d3eeca6 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Tue, 25 Feb 2025 13:45:11 +0100 Subject: [PATCH 01/17] added feature flag and new component FormDesignernavigation --- frontend/app-development/router/routes.tsx | 22 ++++++++++---- .../shared/src/utils/featureToggleUtils.ts | 1 + .../FormDesignerNavigation.module.css | 30 +++++++++++++++++++ .../FormDesignerNavigation.test.tsx | 5 ++++ .../FormDesignerNavigation.tsx | 26 ++++++++++++++++ .../containers/FormDesignNavigation/index.ts | 1 + 6 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css create mode 100644 frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx create mode 100644 frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx create mode 100644 frontend/packages/ux-editor/src/containers/FormDesignNavigation/index.ts diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index 59cafb65330..56928866e57 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -12,9 +12,12 @@ import { useAppVersionQuery } from 'app-shared/hooks/queries'; import React from 'react'; import { usePreviewContext } from '../contexts/PreviewContext'; import { useLayoutContext } from '../contexts/LayoutContext'; -import { StudioPageSpinner } from '@studio/components'; +import { StudioPageSpinner, useLocalStorage } from '@studio/components'; import { useTranslation } from 'react-i18next'; import { AppContentLibrary } from 'app-development/features/appContentLibrary'; +import { FormDesignerNavigation } from '@altinn/ux-editor/containers/FormDesignNavigation'; +import { FeatureFlag, shouldDisplayFeature } from 'app-shared/utils/featureToggleUtils'; +import { useAppConfigQuery } from 'app-development/hooks/queries'; interface IRouteProps { headerTextKey?: string; @@ -45,6 +48,9 @@ const UiEditor = () => { const { data: version, isPending: fetchingVersionIsPending } = useAppVersionQuery(org, app); const { shouldReloadPreview, previewHasLoaded } = usePreviewContext(); const { setSelectedLayoutSetName } = useLayoutContext(); + const [selectedFormLayoutSetName] = useLocalStorage('layoutSet/' + app); + const isTaskNavigationEnabled = shouldDisplayFeature(FeatureFlag.TaskNavigation); + const { data: appConfigData } = useAppConfigQuery(org, app); if (fetchingVersionIsPending) { return ; @@ -53,11 +59,15 @@ const UiEditor = () => { if (!version) return null; return isLatestFrontendVersion(version) ? ( - setSelectedLayoutSetName(layoutSetName)} - /> + isTaskNavigationEnabled && !selectedFormLayoutSetName ? ( + + ) : ( + setSelectedLayoutSetName(layoutSetName)} + /> + ) ) : ( ); diff --git a/frontend/packages/shared/src/utils/featureToggleUtils.ts b/frontend/packages/shared/src/utils/featureToggleUtils.ts index 493794a3abc..defafe43ee5 100644 --- a/frontend/packages/shared/src/utils/featureToggleUtils.ts +++ b/frontend/packages/shared/src/utils/featureToggleUtils.ts @@ -11,6 +11,7 @@ export enum FeatureFlag { MainConfig = 'mainConfig', OptionListEditor = 'optionListEditor', ShouldOverrideAppLibCheck = 'shouldOverrideAppLibCheck', + TaskNavigation = 'taskNavigation', } /* diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css new file mode 100644 index 00000000000..8b6e1ea8d5c --- /dev/null +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css @@ -0,0 +1,30 @@ +.wrapper { + background-color: #e6eff8; +} + +.container { + margin: auto; + padding: var(--fds-spacing-6); + + position: relative; +} + +.panel { + background-color: white; + border-radius: 4px; + box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.05); + padding: var(--fds-spacing-10); + position: relative; +} + +.content { + display: flex; + flex-direction: column; + gap: var(--fds-spacing-10); +} + +.footer { + border-top: 2px solid #efefef; + margin-top: var(--fds-spacing-10); + padding-top: var(--fds-spacing-8); +} diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx new file mode 100644 index 00000000000..35fff044f43 --- /dev/null +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx @@ -0,0 +1,5 @@ +//TODO: Add test case for featureFlags taskNavigation + +//TODO: Add test cases for FormDesignerNavigation component +// 1- Add test for rendring the component +// 2- Add test for the component with heading text sildeSortering diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx new file mode 100644 index 00000000000..a3a4cc95a74 --- /dev/null +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx @@ -0,0 +1,26 @@ +import { Link, Paragraph } from '@digdir/designsystemet-react'; +import React from 'react'; +import classes from './FormDesignerNavigation.module.css'; +import { useTranslation } from 'react-i18next'; + +export type FormDesignerNavigationProps = { + appConfig: string; +}; + +export const FormDesignerNavigation = ({ appConfig }: FormDesignerNavigationProps) => { + const { t } = useTranslation(); + return ( +
+
+
+
+ {appConfig} +
+
+ {t('general.contact')} +
+
+
+
+ ); +}; diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/index.ts b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/index.ts new file mode 100644 index 00000000000..268ea87003d --- /dev/null +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/index.ts @@ -0,0 +1 @@ +export { FormDesignerNavigation } from './FormDesignerNavigation'; From 6c093c36add44c5e364fb3d54a56afec7060f76c Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Tue, 25 Feb 2025 14:37:06 +0100 Subject: [PATCH 02/17] added test for featureFlags --- .../src/utils/featureToggleUtils.test.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/frontend/packages/shared/src/utils/featureToggleUtils.test.ts b/frontend/packages/shared/src/utils/featureToggleUtils.test.ts index bd14bfbdd9e..20820a99fe0 100644 --- a/frontend/packages/shared/src/utils/featureToggleUtils.test.ts +++ b/frontend/packages/shared/src/utils/featureToggleUtils.test.ts @@ -27,6 +27,16 @@ describe('featureToggle localStorage', () => { it('should return false if feature is not enabled in the localStorage', () => { expect(shouldDisplayFeature(FeatureFlag.ShouldOverrideAppLibCheck)).toBeFalsy(); }); + + it('should return true if TaskNavigation is enabled in the localStorage', () => { + typedLocalStorage.setItem('featureFlags', ['taskNavigation']); + expect(shouldDisplayFeature(FeatureFlag.TaskNavigation)).toBeTruthy(); + }); + + it('should return false if TaskNavigation is not enabled in the localStorage', () => { + typedLocalStorage.setItem('featureFlags', ['demo']); + expect(shouldDisplayFeature(FeatureFlag.TaskNavigation)).toBeFalsy(); + }); }); describe('featureToggle url', () => { @@ -69,6 +79,16 @@ describe('featureToggle url', () => { ]); expect(typedLocalStorage.getItem('featureFlags')).toBeNull(); }); + + it('should return true if TaskNavigation is enabled in the url', () => { + window.history.pushState({}, 'PageUrl', '/?featureFlags=taskNavigation'); + expect(shouldDisplayFeature(FeatureFlag.TaskNavigation)).toBeTruthy(); + }); + + it('should return false if TaskNavigation is not enabled in the url', () => { + window.history.pushState({}, 'PageUrl', '/?featureFlags=demo'); + expect(shouldDisplayFeature(FeatureFlag.TaskNavigation)).toBeFalsy(); + }); }); describe('addFeatureToLocalStorage', () => { @@ -89,6 +109,11 @@ describe('addFeatureToLocalStorage', () => { 'shouldOverrideAppLibCheck', ]); }); + + it('should add TaskNavigation to local storage', () => { + addFeatureFlagToLocalStorage(FeatureFlag.TaskNavigation); + expect(typedLocalStorage.getItem('featureFlags')).toEqual(['taskNavigation']); + }); }); describe('removeFeatureFromLocalStorage', () => { From 45871c81089e7939d910a716d57a394694f00cc1 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Tue, 25 Feb 2025 15:15:53 +0100 Subject: [PATCH 03/17] added test for component FormDesignNavigation --- .../FormDesignerNavigation.test.tsx | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx index 35fff044f43..79377df95fb 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.test.tsx @@ -1,5 +1,23 @@ -//TODO: Add test case for featureFlags taskNavigation +import React from 'react'; +import { screen } from '@testing-library/react'; +import { FormDesignerNavigation, type FormDesignerNavigationProps } from './FormDesignerNavigation'; +import { renderWithProviders } from 'app-development/test/mocks'; +import { textMock } from '@studio/testing/mocks/i18nMock'; -//TODO: Add test cases for FormDesignerNavigation component -// 1- Add test for rendring the component -// 2- Add test for the component with heading text sildeSortering +const defaultProps = { + appConfig: 'test', +}; + +describe('FormDesignerNavigation', () => { + it('renders the component with heading text test', () => { + render({ appConfig: 'test' }); + expect(screen.getByText('test')).toBeInTheDocument(); + }); + it('renders the contact link', () => { + render(); + expect(screen.getByRole('link', { name: textMock('general.contact') })).toBeInTheDocument(); + }); +}); + +const render = (props: Partial = {}) => + renderWithProviders()(); From 1b3935852f9ec408bd1ae2a80e68c2df5af61738 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Tue, 25 Feb 2025 15:17:58 +0100 Subject: [PATCH 04/17] update --- .../FormDesignNavigation/FormDesignerNavigation.module.css | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css index 8b6e1ea8d5c..562e1f22fc0 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css @@ -5,7 +5,6 @@ .container { margin: auto; padding: var(--fds-spacing-6); - position: relative; } From 1891db7ae1b91c13183b6e2d4f96ca1d1f7c50a6 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Tue, 25 Feb 2025 21:57:58 +0100 Subject: [PATCH 05/17] fixed coderabbitai warning --- .../app-development/router/routes.test.tsx | 17 ++++++++---- frontend/app-development/router/routes.tsx | 26 ++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index 592711f1a8c..c1b20685f86 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import { routerRoutes } from './routes'; import { RoutePaths } from '../enums/RoutePaths'; import React from 'react'; @@ -36,7 +36,7 @@ describe('routes', () => { it.each(testCases)( 'Renders the %s schema editor page when the app frontend version is %s', - (expectedPackage, frontendVersion) => { + async (expectedPackage, frontendVersion) => { const appVersion: AppVersion = { frontendVersion, backendVersion: '7.0.0', @@ -44,13 +44,20 @@ describe('routes', () => { const queryClient = createQueryClientMock(); queryClient.setQueryData([QueryKey.AppVersion, org, app], appVersion); renderUiEditor(queryClient); - expect(screen.getByTestId(expectedPackage)).toBeInTheDocument(); + expect(await screen.findByTestId(expectedPackage)).toBeInTheDocument(); }, ); - it('renders a loading spinner while fetching frontend version', () => { + it('renders a loading spinner while fetching frontend version', async () => { renderUiEditor(); - expect(screen.getByText(textMock('ux_editor.loading_page'))).toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByTestId('studio-spinner-test-id')).toBeInTheDocument(); + }); + }); + + it('renders a loading spinner while pending', () => { + renderUiEditor(); + expect(screen.getByText(textMock('overview.header_loading'))).toBeInTheDocument(); }); const renderUiEditor = (queryClient: QueryClient = createQueryClientMock()) => diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index 56928866e57..a2c9ebf7ae6 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -9,15 +9,16 @@ import { RoutePaths } from 'app-development/enums/RoutePaths'; import type { AppVersion } from 'app-shared/types/AppVersion'; import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams'; import { useAppVersionQuery } from 'app-shared/hooks/queries'; -import React from 'react'; +import React, { useEffect } from 'react'; import { usePreviewContext } from '../contexts/PreviewContext'; import { useLayoutContext } from '../contexts/LayoutContext'; -import { StudioPageSpinner, useLocalStorage } from '@studio/components'; +import { StudioPageSpinner, StudioSpinner, useLocalStorage } from '@studio/components'; import { useTranslation } from 'react-i18next'; import { AppContentLibrary } from 'app-development/features/appContentLibrary'; import { FormDesignerNavigation } from '@altinn/ux-editor/containers/FormDesignNavigation'; import { FeatureFlag, shouldDisplayFeature } from 'app-shared/utils/featureToggleUtils'; import { useAppConfigQuery } from 'app-development/hooks/queries'; +import { toast } from 'react-toastify'; interface IRouteProps { headerTextKey?: string; @@ -50,7 +51,24 @@ const UiEditor = () => { const { setSelectedLayoutSetName } = useLayoutContext(); const [selectedFormLayoutSetName] = useLocalStorage('layoutSet/' + app); const isTaskNavigationEnabled = shouldDisplayFeature(FeatureFlag.TaskNavigation); - const { data: appConfigData } = useAppConfigQuery(org, app); + + const { + data: appConfigData, + isPending, + isError, + } = useAppConfigQuery(org, app, { + hideDefaultError: true, + }); + + useEffect(() => { + if (isError) { + toast.error(t('overview.fetch_title_error_message')); + } + }, [isError, t]); + + if (isPending) { + return ; + } if (fetchingVersionIsPending) { return ; @@ -60,7 +78,7 @@ const UiEditor = () => { return isLatestFrontendVersion(version) ? ( isTaskNavigationEnabled && !selectedFormLayoutSetName ? ( - + ) : ( Date: Wed, 26 Feb 2025 09:54:47 +0100 Subject: [PATCH 06/17] test --- frontend/app-development/router/routes.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index c1b20685f86..c7cf4ccdf12 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -48,14 +48,14 @@ describe('routes', () => { }, ); - it('renders a loading spinner while fetching frontend version', async () => { + it('renders a loading spinner', async () => { renderUiEditor(); await waitFor(() => { expect(screen.getByTestId('studio-spinner-test-id')).toBeInTheDocument(); }); }); - it('renders a loading spinner while pending', () => { + it('renders a loading spinner message while pending', () => { renderUiEditor(); expect(screen.getByText(textMock('overview.header_loading'))).toBeInTheDocument(); }); From 3153a547b2a17e6d00a6c2e0c889178154a8db8c Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 10:09:25 +0100 Subject: [PATCH 07/17] refacture --- frontend/app-development/router/routes.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index a2c9ebf7ae6..403bcb89ddd 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -76,19 +76,21 @@ const UiEditor = () => { if (!version) return null; - return isLatestFrontendVersion(version) ? ( - isTaskNavigationEnabled && !selectedFormLayoutSetName ? ( - - ) : ( + const renderUiEditorContent = () => { + if (isTaskNavigationEnabled && !selectedFormLayoutSetName && appConfigData) { + return ; + } + + return ( setSelectedLayoutSetName(layoutSetName)} /> - ) - ) : ( - - ); + ); + }; + + return isLatestFrontendVersion(version) ? renderUiEditorContent() : ; }; export const routerRoutes: RouterRoute[] = [ From 76768c01e219929553a119ae9064011be588610b Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 10:13:25 +0100 Subject: [PATCH 08/17] update --- frontend/app-development/router/routes.tsx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index 403bcb89ddd..ca78daf44c5 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -9,7 +9,7 @@ import { RoutePaths } from 'app-development/enums/RoutePaths'; import type { AppVersion } from 'app-shared/types/AppVersion'; import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams'; import { useAppVersionQuery } from 'app-shared/hooks/queries'; -import React, { useEffect } from 'react'; +import React from 'react'; import { usePreviewContext } from '../contexts/PreviewContext'; import { useLayoutContext } from '../contexts/LayoutContext'; import { StudioPageSpinner, StudioSpinner, useLocalStorage } from '@studio/components'; @@ -18,7 +18,6 @@ import { AppContentLibrary } from 'app-development/features/appContentLibrary'; import { FormDesignerNavigation } from '@altinn/ux-editor/containers/FormDesignNavigation'; import { FeatureFlag, shouldDisplayFeature } from 'app-shared/utils/featureToggleUtils'; import { useAppConfigQuery } from 'app-development/hooks/queries'; -import { toast } from 'react-toastify'; interface IRouteProps { headerTextKey?: string; @@ -52,20 +51,10 @@ const UiEditor = () => { const [selectedFormLayoutSetName] = useLocalStorage('layoutSet/' + app); const isTaskNavigationEnabled = shouldDisplayFeature(FeatureFlag.TaskNavigation); - const { - data: appConfigData, - isPending, - isError, - } = useAppConfigQuery(org, app, { + const { data: appConfigData, isPending } = useAppConfigQuery(org, app, { hideDefaultError: true, }); - useEffect(() => { - if (isError) { - toast.error(t('overview.fetch_title_error_message')); - } - }, [isError, t]); - if (isPending) { return ; } From ba2b0d9eac881f8e12f29f6bcd361c93a4528c24 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 10:32:19 +0100 Subject: [PATCH 09/17] update test --- frontend/app-development/router/routes.test.tsx | 4 ++-- frontend/app-development/router/routes.tsx | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index c7cf4ccdf12..a24ef5867c9 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -55,9 +55,9 @@ describe('routes', () => { }); }); - it('renders a loading spinner message while pending', () => { + it('renders a loading spinner while fetching frontend version', () => { renderUiEditor(); - expect(screen.getByText(textMock('overview.header_loading'))).toBeInTheDocument(); + expect(screen.getByText(textMock('ux_editor.loading_page'))).toBeInTheDocument(); }); const renderUiEditor = (queryClient: QueryClient = createQueryClientMock()) => diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index ca78daf44c5..89889dd88c0 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -12,7 +12,7 @@ import { useAppVersionQuery } from 'app-shared/hooks/queries'; import React from 'react'; import { usePreviewContext } from '../contexts/PreviewContext'; import { useLayoutContext } from '../contexts/LayoutContext'; -import { StudioPageSpinner, StudioSpinner, useLocalStorage } from '@studio/components'; +import { StudioPageSpinner, useLocalStorage } from '@studio/components'; import { useTranslation } from 'react-i18next'; import { AppContentLibrary } from 'app-development/features/appContentLibrary'; import { FormDesignerNavigation } from '@altinn/ux-editor/containers/FormDesignNavigation'; @@ -51,14 +51,10 @@ const UiEditor = () => { const [selectedFormLayoutSetName] = useLocalStorage('layoutSet/' + app); const isTaskNavigationEnabled = shouldDisplayFeature(FeatureFlag.TaskNavigation); - const { data: appConfigData, isPending } = useAppConfigQuery(org, app, { + const { data: appConfigData } = useAppConfigQuery(org, app, { hideDefaultError: true, }); - if (isPending) { - return ; - } - if (fetchingVersionIsPending) { return ; } From 243a7c2e023d57f3848912aab1e611906f201494 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 10:49:14 +0100 Subject: [PATCH 10/17] added test --- .../app-development/router/routes.test.tsx | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index a24ef5867c9..b566ac63e4e 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -13,6 +13,7 @@ import { PreviewContextProvider } from '../contexts/PreviewContext'; import { AppDevelopmentContextProvider } from '../contexts/AppDevelopmentContext'; import { textMock } from '@studio/testing/mocks/i18nMock'; import type { QueryClient } from '@tanstack/react-query'; +import { LayoutContext } from 'app-development/contexts/LayoutContext/LayoutContext'; // Mocks: jest.mock('@altinn/ux-editor-v3/SubApp', () => ({ @@ -22,8 +23,45 @@ jest.mock('@altinn/ux-editor/SubApp', () => ({ SubApp: () =>
, })); +jest.mock('@altinn/ux-editor/SubApp', () => ({ + SubApp: ({ onLayoutSetNameChange }: { onLayoutSetNameChange: (name: string) => void }) => { + React.useEffect(() => { + onLayoutSetNameChange('test-layout'); + }, [onLayoutSetNameChange]); + return
; + }, +})); + describe('routes', () => { describe(RoutePaths.UIEditor, () => { + it('calls setSelectedLayoutSetName when layout set changes', async () => { + const setSelectedLayoutSetName = jest.fn(); + + const appVersion: AppVersion = { + frontendVersion: '4.0.0', + backendVersion: '7.0.0', + }; + const queryClient = createQueryClientMock(); + queryClient.setQueryData([QueryKey.AppVersion, org, app], appVersion); + + render( + + + + + + {React.createElement( + routerRoutes.find((route) => route.path === RoutePaths.UIEditor)!.subapp, + )} + + + + + , + ); + expect(await screen.findByTestId('latest version')).toBeInTheDocument(); + expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); + }); type FrontendVersion = null | '3.0.0' | '4.0.0'; type PackageVersion = 'version 3' | 'latest version'; type TestCase = [PackageVersion, FrontendVersion]; From 1c11d907ba7ed54cbb72c36f57cb6ec049520162 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 11:33:14 +0100 Subject: [PATCH 11/17] added test --- frontend/app-development/router/routes.test.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index b566ac63e4e..e41644420c4 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -62,6 +62,15 @@ describe('routes', () => { expect(await screen.findByTestId('latest version')).toBeInTheDocument(); expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); }); + + it('renders nothing when version is undefined', () => { + const queryClient = createQueryClientMock(); + queryClient.setQueryData([QueryKey.AppVersion, org, app], undefined); + renderSubapp(RoutePaths.UIEditor, queryClient); + expect(screen.queryByTestId('latest version')).not.toBeInTheDocument(); + expect(screen.queryByTestId('version 3')).not.toBeInTheDocument(); + }); + type FrontendVersion = null | '3.0.0' | '4.0.0'; type PackageVersion = 'version 3' | 'latest version'; type TestCase = [PackageVersion, FrontendVersion]; From f38acd5d122bfa182eaa311a357239a89ecb95f7 Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 12:59:43 +0100 Subject: [PATCH 12/17] added test --- frontend/app-development/router/routes.test.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index e41644420c4..78b46d8bdae 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -63,12 +63,12 @@ describe('routes', () => { expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); }); - it('renders nothing when version is undefined', () => { + it('Returns null when there is no AppVersion', async () => { const queryClient = createQueryClientMock(); - queryClient.setQueryData([QueryKey.AppVersion, org, app], undefined); - renderSubapp(RoutePaths.UIEditor, queryClient); - expect(screen.queryByTestId('latest version')).not.toBeInTheDocument(); + queryClient.setQueryData([QueryKey.AppVersion, org, app], null); + renderUiEditor(queryClient); expect(screen.queryByTestId('version 3')).not.toBeInTheDocument(); + expect(screen.queryByTestId('latest version')).not.toBeInTheDocument(); }); type FrontendVersion = null | '3.0.0' | '4.0.0'; From ca1aa89f3a879ba44c241fa4d79e0fbccb93f54e Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 13:25:38 +0100 Subject: [PATCH 13/17] update test --- frontend/app-development/router/routes.test.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index 78b46d8bdae..9bf07dc773a 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -59,8 +59,14 @@ describe('routes', () => { , ); + + await waitFor(() => { + expect(setSelectedLayoutSetName).toHaveBeenCalledTimes(1); + }); + await waitFor(() => { + expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); + }); expect(await screen.findByTestId('latest version')).toBeInTheDocument(); - expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); }); it('Returns null when there is no AppVersion', async () => { From b2c67bee92c4702587ee842fad371cafdec68fae Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 14:44:47 +0100 Subject: [PATCH 14/17] fixed css --- .../FormDesignNavigation/FormDesignerNavigation.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css index 562e1f22fc0..bf1753a63c8 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css @@ -10,7 +10,7 @@ .panel { background-color: white; - border-radius: 4px; + border-radius: var(--fds-border_radius-medium); box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.05); padding: var(--fds-spacing-10); position: relative; From 2c9c4ea3fe2bfd5e9c9add415adfeee65e27c78b Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Wed, 26 Feb 2025 21:27:25 +0100 Subject: [PATCH 15/17] update test --- .../app-development/router/routes.test.tsx | 62 +++++++++++-------- frontend/app-development/router/routes.tsx | 8 ++- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/frontend/app-development/router/routes.test.tsx b/frontend/app-development/router/routes.test.tsx index 9bf07dc773a..9cbe1ab8b18 100644 --- a/frontend/app-development/router/routes.test.tsx +++ b/frontend/app-development/router/routes.test.tsx @@ -1,5 +1,5 @@ import { render, screen, waitFor } from '@testing-library/react'; -import { routerRoutes } from './routes'; +import { routerRoutes, UiEditor } from './routes'; import { RoutePaths } from '../enums/RoutePaths'; import React from 'react'; import { createQueryClientMock } from 'app-shared/mocks/queryClientMock'; @@ -14,6 +14,7 @@ import { AppDevelopmentContextProvider } from '../contexts/AppDevelopmentContext import { textMock } from '@studio/testing/mocks/i18nMock'; import type { QueryClient } from '@tanstack/react-query'; import { LayoutContext } from 'app-development/contexts/LayoutContext/LayoutContext'; +import { SubApp as UiEditorLatest } from '@altinn/ux-editor/SubApp'; // Mocks: jest.mock('@altinn/ux-editor-v3/SubApp', () => ({ @@ -32,41 +33,48 @@ jest.mock('@altinn/ux-editor/SubApp', () => ({ }, })); +const renderWithProviders = ( + ui: React.ReactElement, + queryClient: QueryClient, + layoutContextValue?: any, +) => { + return render( + + + + + {ui} + + + + , + ); +}; + describe('routes', () => { describe(RoutePaths.UIEditor, () => { - it('calls setSelectedLayoutSetName when layout set changes', async () => { + it('calls setSelectedLayoutSetName when onLayoutSetNameChange is triggered', () => { const setSelectedLayoutSetName = jest.fn(); - + const queryClient = createQueryClientMock(); const appVersion: AppVersion = { frontendVersion: '4.0.0', backendVersion: '7.0.0', }; - const queryClient = createQueryClientMock(); queryClient.setQueryData([QueryKey.AppVersion, org, app], appVersion); - - render( - - - - - - {React.createElement( - routerRoutes.find((route) => route.path === RoutePaths.UIEditor)!.subapp, - )} - - - - - , - ); - - await waitFor(() => { - expect(setSelectedLayoutSetName).toHaveBeenCalledTimes(1); + const { rerender } = renderWithProviders(, queryClient, { + setSelectedLayoutSetName, }); - await waitFor(() => { - expect(setSelectedLayoutSetName).toHaveBeenCalledWith('test-layout'); - }); - expect(await screen.findByTestId('latest version')).toBeInTheDocument(); + const layoutSetName = 'test-layout'; + const onLayoutSetNameChange = jest.fn(); + rerender( + , + ); + onLayoutSetNameChange(layoutSetName); + expect(setSelectedLayoutSetName).toHaveBeenCalledWith(layoutSetName); }); it('Returns null when there is no AppVersion', async () => { diff --git a/frontend/app-development/router/routes.tsx b/frontend/app-development/router/routes.tsx index 89889dd88c0..3b717a60cbf 100644 --- a/frontend/app-development/router/routes.tsx +++ b/frontend/app-development/router/routes.tsx @@ -42,7 +42,7 @@ const latestFrontendVersion = '4'; const isLatestFrontendVersion = (version: AppVersion): boolean => version?.frontendVersion?.startsWith(latestFrontendVersion); -const UiEditor = () => { +export const UiEditor = () => { const { org, app } = useStudioEnvironmentParams(); const { t } = useTranslation(); const { data: version, isPending: fetchingVersionIsPending } = useAppVersionQuery(org, app); @@ -66,11 +66,15 @@ const UiEditor = () => { return ; } + const handleLayoutSetNameChange = (layoutSetName: string) => { + setSelectedLayoutSetName(layoutSetName); + }; + return ( setSelectedLayoutSetName(layoutSetName)} + onLayoutSetNameChange={handleLayoutSetNameChange} /> ); }; From ac40bbc1d96c85af9f123947c787540d128a281d Mon Sep 17 00:00:00 2001 From: Jamal Alabdullah Date: Thu, 27 Feb 2025 10:58:45 +0100 Subject: [PATCH 16/17] update size for app name --- .../FormDesignNavigation/FormDesignerNavigation.module.css | 4 ++++ .../FormDesignNavigation/FormDesignerNavigation.tsx | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css index bf1753a63c8..25fbdb4ca1e 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.module.css @@ -8,6 +8,10 @@ position: relative; } +.header { + font-size: x-large; +} + .panel { background-color: white; border-radius: var(--fds-border_radius-medium); diff --git a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx index a3a4cc95a74..d9f3cd11706 100644 --- a/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx +++ b/frontend/packages/ux-editor/src/containers/FormDesignNavigation/FormDesignerNavigation.tsx @@ -1,4 +1,4 @@ -import { Link, Paragraph } from '@digdir/designsystemet-react'; +import { Link } from '@digdir/designsystemet-react'; import React from 'react'; import classes from './FormDesignerNavigation.module.css'; import { useTranslation } from 'react-i18next'; @@ -14,7 +14,7 @@ export const FormDesignerNavigation = ({ appConfig }: FormDesignerNavigationProp
- {appConfig} +
{appConfig}