Skip to content

Commit

Permalink
use new getOptionList by optionListId
Browse files Browse the repository at this point in the history
  • Loading branch information
standeren committed Dec 2, 2024
1 parent 2761798 commit 1e7c4ef
Show file tree
Hide file tree
Showing 25 changed files with 262 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@ jest.mock(
}),
);

const optionListsMock: OptionsLists = {
list1: [{ label: 'label', value: 'value' }],
};
const optionListIdsMock: string[] = ['list1'];

describe('AppContentLibrary', () => {
afterEach(jest.clearAllMocks);

it('renders the AppContentLibrary with codeLists and images resources available in the content menu', () => {
renderAppContentLibrary(optionListsMock);
renderAppContentLibrary(optionListIdsMock);
const libraryTitle = screen.getByRole('heading', {
name: textMock('app_content_library.landing_page.title'),
});
Expand All @@ -67,7 +65,7 @@ describe('AppContentLibrary', () => {

it('calls onUploadOptionList when onUploadCodeList is triggered', async () => {
const user = userEvent.setup();
renderAppContentLibrary(optionListsMock);
renderAppContentLibrary(optionListIdsMock);
await goToLibraryPage(user, 'code_lists');
const uploadCodeListButton = screen.getByRole('button', { name: uploadCodeListButtonTextMock });
await user.click(uploadCodeListButton);
Expand All @@ -77,7 +75,7 @@ describe('AppContentLibrary', () => {

it('calls onUpdateOptionList when onUpdateCodeList is triggered', async () => {
const user = userEvent.setup();
renderAppContentLibrary(optionListsMock);
renderAppContentLibrary(optionListIdsMock);
await goToLibraryPage(user, 'code_lists');
const updateCodeListButton = screen.getByRole('button', { name: updateCodeListButtonTextMock });
await user.click(updateCodeListButton);
Expand All @@ -99,10 +97,10 @@ const goToLibraryPage = async (user: UserEvent, libraryPage: string) => {
await user.click(libraryPageNavTile);
};

const renderAppContentLibrary = (optionLists: OptionsLists = {}) => {
const renderAppContentLibrary = (optionListIds: string[] = []) => {
const queryClientMock = createQueryClientMock();
if (Object.keys(optionLists).length) {
queryClientMock.setQueryData([QueryKey.OptionLists, org, app], optionLists);
if (optionListIds.length) {
queryClientMock.setQueryData([QueryKey.OptionListIds, org, app], optionListIds);
}
renderWithProviders({}, queryClientMock)(<AppContentLibrary />);
};
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import type { CodeListWithMetadata } from '@studio/content-library';
import type { CodeListWithMetadata, OnGetCodeListResult } from '@studio/content-library';
import { ResourceContentLibraryImpl } from '@studio/content-library';
import React from 'react';
import { useOptionListsQuery } from 'app-shared/hooks/queries/useOptionListsQuery';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { convertOptionListsToCodeLists } from './utils/convertOptionListsToCodeLists';
import { convertOptionsListToCodeListResult } from './utils/convertOptionsListToCodeListResult';
import { StudioPageSpinner } from '@studio/components';
import { useTranslation } from 'react-i18next';
import { useAddOptionListMutation, useUpdateOptionListMutation } from 'app-shared/hooks/mutations';
import { useOptionListIdsQuery } from '@altinn/ux-editor/hooks/queries/useOptionListIdsQuery';
import { useGetOptionListQuery } from 'app-shared/hooks/queries';

export function AppContentLibrary(): React.ReactElement {
const { org, app } = useStudioEnvironmentParams();
const { t } = useTranslation();
const {
data: optionLists,
isPending: optionListsPending,
isError: optionListsError,
} = useOptionListsQuery(org, app);
const { data: optionListIds, isPending: optionListIdsPending } = useOptionListIdsQuery(org, app);
const getOptionList = useGetOptionListQuery(org, app);
const { mutate: uploadOptionList } = useAddOptionListMutation(org, app);
const { mutate: updateOptionList } = useUpdateOptionListMutation(org, app);

if (optionListsPending)
if (optionListIdsPending)
return <StudioPageSpinner spinnerTitle={t('general.loading')}></StudioPageSpinner>;

const codeLists = convertOptionListsToCodeLists(optionLists);
const handleGetOptionList = (optionListId: string): OnGetCodeListResult => {
const { data: optionList, isError: optionListError } = getOptionList(optionListId);
return convertOptionsListToCodeListResult(optionListId, optionList, optionListError);
};

const handleUpload = (file: File) => {
uploadOptionList(file);
Expand All @@ -36,10 +37,10 @@ export function AppContentLibrary(): React.ReactElement {
pages: {
codeList: {
props: {
codeLists: codeLists,
codeListIds: optionListIds,
onGetCodeList: handleGetOptionList,
onUpdateCodeList: handleUpdate,
onUploadCodeList: handleUpload,
fetchDataError: optionListsError,
},
},
images: {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { OnGetCodeListResult } from '@studio/content-library';
import { convertOptionsListToCodeListResult } from './convertOptionsListToCodeListResult';
import type { OptionsList } from 'app-shared/types/api/OptionsLists';

describe('convertOptionsListToCodeListResult', () => {
it('converts option list to code list result correctly', () => {
const optionList: OptionsList = [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
];
const optionListId: string = 'optionListId';
const result: OnGetCodeListResult = convertOptionsListToCodeListResult(
optionListId,
optionList,
false,
);
expect(result).toEqual({
codeListWithMetadata: {
title: optionListId,
codeList: [
{ label: 'Option 1', value: '1' },
{ label: 'Option 2', value: '2' },
],
},
isError: false,
});
});

it('sets isError to true in result when getOptionsList returns error', () => {
const optionListId: string = 'optionListId';
const result: OnGetCodeListResult = convertOptionsListToCodeListResult(
optionListId,
undefined,
false,
);
expect(result).toEqual({
codeListWithMetadata: {
title: optionListId,
codeList: undefined,
},
isError: false,
});
});

it('returns a result with empty code list array when the input option list is empty', () => {
const optionList: OptionsList = [];
const optionListId: string = 'optionListId';
const result: OnGetCodeListResult = convertOptionsListToCodeListResult(
optionListId,
optionList,
false,
);
expect(result).toEqual({
codeListWithMetadata: { title: optionListId, codeList: [] },
isError: false,
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { OptionsList } from 'app-shared/types/api/OptionsLists';
import type { OnGetCodeListResult } from '@studio/content-library';

export const convertOptionsListToCodeListResult = (
optionListId: string,
optionsList: OptionsList,
isError: boolean,
): OnGetCodeListResult => {
const codeListWithMetadata = { title: optionListId, codeList: optionsList };
return {
codeListWithMetadata: codeListWithMetadata,
isError: isError,
};
};
2 changes: 1 addition & 1 deletion frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"app_content_library.code_lists.create_new_code_list_modal_title": "Lag ny kodeliste",
"app_content_library.code_lists.create_new_code_list_name": "Navn",
"app_content_library.code_lists.edit_code_list_placeholder_text": "Her kommer det redigeringsmuligheter snart",
"app_content_library.code_lists.fetch_error": "Kunne ikke hente kodelister fra appen.",
"app_content_library.code_lists.fetch_error": "Kunne ikke hente kodeliste fra appen.",
"app_content_library.code_lists.info_box.description": "En kodeliste er en liste med strukturerte data. Den inneholder definerte alternativer som alle har en unik kode. For eksempel kan du ha en kodeliste med kommunenavn i skjemaet ditt, som brukerne kan velge fra en nedtrekksmeny. Brukerne ser bare navnet, ikke koden.",
"app_content_library.code_lists.info_box.title": "Hva er en kodeliste?",
"app_content_library.code_lists.no_content": "Dette biblioteket har ingen kodelister",
Expand Down
12 changes: 7 additions & 5 deletions frontend/libs/studio-content-library/mocks/mockPagesConfig.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import type { PagesConfig } from '../src/types/PagesProps';
import type { OnGetCodeListResult } from '../src';

const onGetCodeListResult = (codeListId: string): OnGetCodeListResult => {
return { codeListWithMetadata: { title: codeListId, codeList: [] }, isError: false };
};

export const mockPagesConfig: PagesConfig = {
codeList: {
props: {
codeLists: [
{ title: 'CodeList1', codeList: [] },
{ title: 'CodeList2', codeList: [] },
],
codeListIds: ['CodeList1', 'CodeList2'],
onGetCodeList: onGetCodeListResult,
onUpdateCodeList: () => {},
onUploadCodeList: () => {},
fetchDataError: false,
},
},
images: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import type { CodeListProps, CodeListWithMetadata } from './CodeList';
import type { CodeListProps, OnGetCodeListResult } from './CodeList';
import { CodeList } from './CodeList';
import { textMock } from '@studio/testing/mocks/i18nMock';

const onUpdateCodeListMock = jest.fn();
const onUploadCodeListMock = jest.fn();
const codeListName = 'codeList';
const codeListMock: CodeListWithMetadata = {
title: codeListName,
codeList: [{ value: 'value', label: 'label' }],
};
const codeListMock = [{ value: 'value', label: 'label' }];
const onGetCodeListMock: jest.Mock<OnGetCodeListResult, [codeListId: string]> = jest.fn(
(codeListId: string) => {
return { codeListWithMetadata: { title: codeListId, codeList: codeListMock }, isError: false };
},
);

describe('CodeList', () => {
it('renders the codeList heading', () => {
Expand Down Expand Up @@ -48,33 +50,15 @@ describe('CodeList', () => {
const codeListAccordion = screen.getByRole('button', { name: codeListName });
expect(codeListAccordion).toBeInTheDocument();
});

it('renders error message if error fetching option lists occurred', () => {
renderCodeList({ fetchDataError: true });
const errorMessage = screen.getByText(textMock('app_content_library.code_lists.fetch_error'));
expect(errorMessage).toBeInTheDocument();
});
});

const defaultCodeListProps: CodeListProps = {
codeLists: [codeListMock],
codeListIds: [codeListName],
onGetCodeList: onGetCodeListMock,
onUpdateCodeList: onUpdateCodeListMock,
onUploadCodeList: onUploadCodeListMock,
fetchDataError: false,
};

const renderCodeList = ({
codeLists,
onUpdateCodeList,
onUploadCodeList,
fetchDataError,
}: Partial<CodeListProps> = defaultCodeListProps) => {
render(
<CodeList
codeLists={codeLists}
onUpdateCodeList={onUpdateCodeList}
onUploadCodeList={onUploadCodeList}
fetchDataError={fetchDataError}
/>,
);
const renderCodeList = (props: Partial<CodeListProps> = {}) => {
render(<CodeList {...defaultCodeListProps} {...props} />);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { StudioHeading, StudioPageError } from '@studio/components';
import { StudioHeading } from '@studio/components';
import type { CodeList as StudioComponentCodeList } from '@studio/components';
import { useTranslation } from 'react-i18next';
import { CodeListsActionsBar } from './CodeListsActionsBar';
Expand All @@ -12,32 +12,37 @@ export type CodeListWithMetadata = {
title: string;
};

export type OnGetCodeListResult = {
codeListWithMetadata: CodeListWithMetadata | undefined;
isError: boolean;
};

export type CodeListProps = {
codeLists: CodeListWithMetadata[];
codeListIds: string[];
onGetCodeList: (codeListId: string) => OnGetCodeListResult;
onUpdateCodeList: (updatedCodeList: CodeListWithMetadata) => void;
onUploadCodeList: (uploadedCodeList: File) => void;
fetchDataError: boolean;
};
export function CodeList({
codeLists,
codeListIds,
onGetCodeList,
onUpdateCodeList,
onUploadCodeList,
fetchDataError,
}: CodeListProps): React.ReactElement {
const { t } = useTranslation();

if (fetchDataError)
return <StudioPageError message={t('app_content_library.code_lists.fetch_error')} />;

return (
<div className={classes.codeListsContainer}>
<StudioHeading size='small'>{t('app_content_library.code_lists.page_name')}</StudioHeading>
<CodeListsCounterMessage codeListsCount={codeLists.length} />
<CodeListsCounterMessage codeListsCount={codeListIds.length} />
<CodeListsActionsBar
onUploadCodeList={onUploadCodeList}
onUpdateCodeList={onUpdateCodeList}
/>
<CodeLists codeLists={codeLists} onUpdateCodeList={onUpdateCodeList} />
<CodeLists
codeListIds={codeListIds}
onGetCodeList={onGetCodeList}
onUpdateCodeList={onUpdateCodeList}
/>
</div>
);
}
Loading

0 comments on commit 1e7c4ef

Please sign in to comment.