Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: "Upload codelist" functionality in component config #13763

Merged
merged 43 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4b20b88
Fix link in codelist config.
Konrad-Simso Oct 8, 2024
89a22f2
Upload button added.
Konrad-Simso Oct 10, 2024
f627d58
Edit language and fix typing.
Konrad-Simso Oct 10, 2024
ce088e4
Fix linting, rename variable and allow trailing commas, it gets fixed…
Konrad-Simso Oct 10, 2024
9cc37a3
Rename useValidateFileName.ts to validateFileNameUtils.ts
Konrad-Simso Oct 10, 2024
9a23d27
Add test for useAddOptionMutation.ts
Konrad-Simso Oct 10, 2024
e199eaf
Add tests for EditCodeList.tsx and remove a toast as it's not correct…
Konrad-Simso Oct 10, 2024
73e8b3b
Edit tests and remove unused imports
Konrad-Simso Oct 10, 2024
627433d
Rename hook to use react-hook rules.
Konrad-Simso Oct 10, 2024
1b5bb7a
Edit filename again
Konrad-Simso Oct 10, 2024
da0bb76
Render hook correctly in test file.
Konrad-Simso Oct 10, 2024
d9542a1
Fix whitespaces in backend for linting.
Konrad-Simso Oct 10, 2024
ac92608
Fixing spacing
Konrad-Simso Oct 10, 2024
f230629
Move file out of Utils folder, since it's a React hook and not a util…
Konrad-Simso Oct 10, 2024
efd12b8
Endringer fra review.
Konrad-Simso Oct 11, 2024
541efa4
Refactor useValidateFileName into smaller utils functions and move re…
Konrad-Simso Oct 11, 2024
1fb11bf
- Rename function in validateFileNameUtils.ts
Konrad-Simso Oct 11, 2024
bbc4c79
- Add check for when FormField should be visible.
Konrad-Simso Oct 11, 2024
b24128c
Remove unused import.
Konrad-Simso Oct 11, 2024
6819cfa
- Less generic catch.
Konrad-Simso Oct 11, 2024
3308902
Remove unused imports again
Konrad-Simso Oct 11, 2024
735a0a1
Edit styling
Konrad-Simso Oct 14, 2024
1af9611
Merge branch 'main' into feature/codelist-configuration
Konrad-Simso Oct 14, 2024
155196c
Remove a test and fix 2 tests.
Konrad-Simso Oct 14, 2024
2395cec
Edit test and replace forEach with for of loops for iterator object.
Konrad-Simso Oct 15, 2024
ae5ccbf
Remove unused parameter, extract filename from File
Konrad-Simso Oct 15, 2024
06087e3
Changes from 2nd review:
Konrad-Simso Oct 15, 2024
8640803
fixed typing of props, and changed an error message.
Konrad-Simso Oct 16, 2024
fd06550
Simplify file uploader component
TomasEng Oct 16, 2024
9a603ca
Update file name
TomasEng Oct 16, 2024
2b5218a
Update reference to updated file name
TomasEng Oct 16, 2024
6f2b3a0
Edit import statement
Konrad-Simso Oct 16, 2024
1f7ae0a
Updated `FileUploaderWithValidation.tsx`
Konrad-Simso Oct 16, 2024
9182ce8
Merge branch 'simplify-file-uploader' into feature/codelist-configura…
Konrad-Simso Oct 16, 2024
55609b0
Refactoring
Konrad-Simso Oct 16, 2024
a594d40
Update tests
Konrad-Simso Oct 16, 2024
7ae920d
Merge branch 'main' into feature/codelist-configuration
TomasEng Oct 17, 2024
1a05b9e
Updates from 3rd review
Konrad-Simso Oct 17, 2024
388d011
Update nb.json and edit texts for tests.
Konrad-Simso Oct 17, 2024
34cbb40
Update test
Konrad-Simso Oct 17, 2024
c0fa350
Updates from testing:
Konrad-Simso Oct 22, 2024
4aa4506
Merge branch 'main' into feature/codelist-configuration
ErlingHauan Oct 22, 2024
a853e5f
Fix type error
ErlingHauan Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions backend/src/Designer/Controllers/OptionsController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json;

Check warning on line 3 in backend/src/Designer/Controllers/OptionsController.cs

View workflow job for this annotation

GitHub Actions / Format check

Using directive is unnecessary.
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Helpers;
Expand Down Expand Up @@ -128,6 +130,32 @@
return Ok(newOptionsList);
}

/// <summary>
/// Create new options list.
/// </summary>
/// <param name="org">Unique identifier of the organisation responsible for the app.</param>
/// <param name="repo">Application identifier which is unique within an organisation.</param>
/// <param name="file">File being uploaded.</param>
/// <param name="cancellationToken"><see cref="CancellationToken"/> that observes if operation is cancelled.</param>
[HttpPost]
[Route("upload")]
public async Task<IActionResult> UploadFile(string org, string repo, [FromForm] IFormFile file, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext);
string fileName = file.FileName.Replace(".json", "");

try
{
List<Option> newOptionsList = await _optionsService.UploadNewOption(org, repo, developer, fileName, file, cancellationToken);
return Ok(newOptionsList);
}
catch (Exception e)
{
return BadRequest(e.Message);
}
Fixed Show fixed Hide fixed
}

/// <summary>
/// Deletes an option list.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,12 +767,15 @@ public async Task<string> GetOptionsList(string optionsListId, CancellationToken
/// <param name="payload">The contents of the new options list as a string</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
/// <returns>The new options list as a string.</returns>
public async Task<string> CreateOrOverwriteOptionsList(string optionsListId, string payload, CancellationToken cancellationToken = default)
public async Task<string> CreateOrOverwriteOptionsList(string optionsListId, List<Option> payload, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();

var serialiseOptions = new JsonSerializerOptions { WriteIndented = true };
string payloadString = JsonSerializer.Serialize(payload, serialiseOptions);

string optionsFilePath = Path.Combine(OptionsFolderPath, $"{optionsListId}.json");
await WriteTextByRelativePathAsync(optionsFilePath, payload, true, cancellationToken);
await WriteTextByRelativePathAsync(optionsFilePath, payloadString, true, cancellationToken);
string fileContent = await ReadTextByRelativePathAsync(optionsFilePath, cancellationToken);

return fileContent;
Expand Down
27 changes: 25 additions & 2 deletions backend/src/Designer/Services/Implementation/OptionsService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Models;
using Altinn.Studio.Designer.Services.Interfaces;
using LibGit2Sharp;
using Microsoft.AspNetCore.Http;

namespace Altinn.Studio.Designer.Services.Implementation;

Expand Down Expand Up @@ -57,13 +59,34 @@
cancellationToken.ThrowIfCancellationRequested();
var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, repo, developer);

string payloadString = JsonSerializer.Serialize(payload, new JsonSerializerOptions() { WriteIndented = true });
string updatedOptionsString = await altinnAppGitRepository.CreateOrOverwriteOptionsList(optionsListId, payloadString, cancellationToken);
string updatedOptionsString = await altinnAppGitRepository.CreateOrOverwriteOptionsList(optionsListId, payload, cancellationToken);
var updatedOptions = JsonSerializer.Deserialize<List<Option>>(updatedOptionsString);

return updatedOptions;
}

/// <inheritdoc />
public async Task<List<Option>> UploadNewOption(string org, string repo, string developer, string optionsListId, IFormFile payload, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();

List<Option> deserializedOptions = JsonSerializer.Deserialize<List<Option>>(payload.OpenReadStream(),
new JsonSerializerOptions { WriteIndented = true, AllowTrailingCommas = true });

foreach (Option option in deserializedOptions)
{
if (string.IsNullOrEmpty(option.Value) || string.IsNullOrEmpty(option.Label))
{
throw new Exception("Uploaded file is missing one of the following attributes for a option: value or label.");
}
}
Fixed Show fixed Hide fixed

var altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository(org, repo, developer);
await altinnAppGitRepository.CreateOrOverwriteOptionsList(optionsListId, deserializedOptions, cancellationToken);

return deserializedOptions;
}

/// <inheritdoc />
public void DeleteOptionsList(string org, string repo, string developer, string optionsListId)
{
Expand Down
13 changes: 13 additions & 0 deletions backend/src/Designer/Services/Interfaces/IOptionsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Models;
using Microsoft.AspNetCore.Http;

namespace Altinn.Studio.Designer.Services.Interfaces;

Expand Down Expand Up @@ -42,6 +43,18 @@ public interface IOptionsService
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
public Task<List<Option>> CreateOrOverwriteOptionsList(string org, string repo, string developer, string optionsListId, List<Option> payload, CancellationToken cancellationToken = default);

/// <summary>
/// Adds a new option to the option list.
/// If the file already exists, it will be overwritten.
/// </summary>
/// <param name="org">Orginisation</param>
/// <param name="repo">Repository</param>
/// <param name="developer">Username of developer</param>
/// <param name="optionsListId">Name of the new options list</param>
/// <param name="payload">The options list contents</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that observes if operation is cancelled.</param>
public Task<List<Option>> UploadNewOption(string org, string repo, string developer, string optionsListId, IFormFile payload, CancellationToken cancellationToken = default);

/// <summary>
/// Deletes an options list from the app repository.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public async Task CreateOrOverwriteOptions_WithAppThatHasNoOptionLists_ShouldCre
string newOptionsListString = JsonSerializer.Serialize(newOptionsList, jsonOptions);

// Act
string savedOptionsList = await altinnAppGitRepository.CreateOrOverwriteOptionsList(newOptionName, newOptionsListString);
string savedOptionsList = await altinnAppGitRepository.CreateOrOverwriteOptionsList(newOptionName, newOptionsList);

// Assert
Assert.Equal(newOptionsListString, savedOptionsList);
Expand Down Expand Up @@ -372,7 +372,7 @@ public async Task CreateOrOverwriteOptions_WithAppThatHasOptionLists_ShouldOverw
string newOptionsListString = JsonSerializer.Serialize(newOptionsList, jsonOptions);

// Act
string savedOptionsList = await altinnAppGitRepository.CreateOrOverwriteOptionsList(newOptionName, newOptionsListString);
string savedOptionsList = await altinnAppGitRepository.CreateOrOverwriteOptionsList(newOptionName, newOptionsList);

// Assert
Assert.Equal(newOptionsListString, savedOptionsList);
Expand Down
4 changes: 4 additions & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,9 @@
"ux_editor.modal_properties_code_list_read_more": "<0 href=\"{{optionsDocs}}\" >Les mer om kodelister</0>",
"ux_editor.modal_properties_code_list_read_more_dynamic": "<0 href=\"{{optionsDocs}}\" >Les mer om dynamiske kodelister</0>",
"ux_editor.modal_properties_code_list_read_more_static": "<0 href=\"{{optionsDocs}}\" >Les mer om statiske kodelister</0>",
"ux_editor.modal_properties_code_list_upload": "Last opp din egen kodeliste",
"ux_editor.modal_properties_code_list_upload_duplicate_error": "Opplastning feilet, du prøvde å laste opp en fil som finnes fra før.",
TomasEng marked this conversation as resolved.
Show resolved Hide resolved
"ux_editor.modal_properties_code_list_upload_success": "Filen ble lastet opp.",
"ux_editor.modal_properties_component_change_id": "Komponent-ID",
"ux_editor.modal_properties_component_change_id_information": "Ved redigering av komponent ID vil Studio automatisk oppdatere IDen der den er brukt som referanse, men det er ikke garantert at alle eksemplarer er oppdatert.",
"ux_editor.modal_properties_component_id_not_unique_error": "Komponenten må ha en unik ID",
Expand Down Expand Up @@ -1575,6 +1578,7 @@
"ux_editor.modal_text": "Tekst",
"ux_editor.modal_text_resource_body": "Tekstinnhold",
"ux_editor.modal_text_resource_body_add": "Legg til tekst",
"ux_editor.model_properties_code_list_filename_error": "Filnavnet er ugyldig. Du kan bruke tall og store og små bokstaver fra det norske alfabetet, og understrek, punktum og bindestrek. Filenavnet må starte med en engelsk bokstav",
TomasEng marked this conversation as resolved.
Show resolved Hide resolved
"ux_editor.multi_page_warning": "Denne siden inneholder grupper med flere sider. Denne funksjonaliteten er på nåværende tidspunkt ikke støttet i Altinn Studio. Du kan se og redigere komponentene, men ikke sideinformasjonen. Hvis en komponent legges til eller flyttes i en slik gruppe, blir den automatisk plassert på samme side som komponenten over.",
"ux_editor.no_components_selected": "Velg en side for å se forhåndsvisningen",
"ux_editor.no_text": "Ingen tekst",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type FileValidation = {
};

export type StudioFileUploaderProps = {
className?: string;
onUploadFile: (file: FormData, fileName: string) => void;
accept?: string;
size?: StudioButtonProps['size'];
Expand All @@ -33,6 +34,7 @@ export type StudioFileUploaderProps = {
export const StudioFileUploader = forwardRef<HTMLElement, StudioFileUploaderProps>(
(
{
className,
onUploadFile,
accept,
size,
Expand Down Expand Up @@ -60,7 +62,7 @@ export const StudioFileUploader = forwardRef<HTMLElement, StudioFileUploaderProp
};

return (
<form onSubmit={handleSubmit}>
<form className={className} onSubmit={handleSubmit}>
<input
data-testid={dataTestId}
type='file'
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/shared/src/api/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
altinn2DelegationsMigrationPath,
imagePath,
addImagePath,
optionListPath,
} from 'app-shared/api/paths';
import type { AddLanguagePayload } from 'app-shared/types/api/AddLanguagePayload';
import type { AddRepoParams } from 'app-shared/types/api';
Expand Down Expand Up @@ -113,6 +114,7 @@ export const updateAppPolicy = (org: string, app: string, payload: Policy) => pu
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 uploadDataModel = (org: string, app: string, form: FormData) => post<void, FormData>(dataModelsUploadPath(org, app), form, { headers: { 'Content-Type': 'multipart/form-data' } });
export const uploadOptionList = (org: string, app: string, payload: FormData) => post<void, FormData>(optionListPath(org, app), payload, { headers: { 'Content-Type': 'multipart/form-data' } });
export const upsertTextResources = (org: string, app: string, language: string, payload: ITextResourcesObjectFormat) => put<ITextResourcesObjectFormat>(textResourcesPath(org, app, language), payload);

// Resourceadm
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/shared/src/api/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const dataModelAddXsdFromRepoPath = (org, app, filePath) => `${basePath}/
export const ruleHandlerPath = (org, app, layoutSetName) => `${basePath}/${org}/${app}/app-development/rule-handler?${s({ layoutSetName })}`; // Get, Post
export const widgetSettingsPath = (org, app) => `${basePath}/${org}/${app}/app-development/widget-settings`; // Get
export const optionListsPath = (org, app) => `${basePath}/${org}/${app}/options/option-lists`; // Get
export const optionListPath = (org, app) => `${basePath}/${org}/${app}/options/upload/`; // Post
export const optionListIdsPath = (org, app) => `${basePath}/${org}/${app}/app-development/option-list-ids`; // Get
export const ruleConfigPath = (org, app, layoutSetName) => `${basePath}/${org}/${app}/app-development/rule-config?${s({ layoutSetName })}`; // Get, Post
export const appMetadataModelIdsPath = (org, app, onlyUnReferenced) => `${basePath}/${org}/${app}/app-development/model-ids?${s({ onlyUnReferenced })}`; // Get
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/shared/src/mocks/queriesMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const queriesMock: ServicesContextProps = {
updateAppMetadata: jest.fn().mockImplementation(() => Promise.resolve()),
updateAppConfig: jest.fn().mockImplementation(() => Promise.resolve()),
uploadDataModel: jest.fn().mockImplementation(() => Promise.resolve<JsonSchema>({})),
uploadOptionList: jest.fn().mockImplementation(() => Promise.resolve()),
upsertTextResources: jest
.fn()
.mockImplementation(() => Promise.resolve<ITextResourcesObjectFormat>({})),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.studioFileUploader {
padding-top: var(--fds-spacing-4);
}

.linkStaticCodeLists {
margin-bottom: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { textMock } from '@studio/testing/mocks/i18nMock';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import type { FormComponent } from '../../../../../types/FormComponent';
import { fileSelectorInputId } from '@studio/testing/testids';

const mockComponent: FormComponent<ComponentType.Dropdown> = {
id: 'c24d0812-0c34-4582-8f31-ff4ce9795e96',
Expand Down Expand Up @@ -45,7 +46,7 @@
});

expect(
await screen.findByText(textMock('ux_editor.modal_properties_no_options_found_message')),

Check failure on line 49 in frontend/packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx

View workflow job for this annotation

GitHub Actions / Testing

EditCodeList › should render the component when optionListIds is empty

Unable to find an element with the text: [mockedText(ux_editor.modal_properties_no_options_found_message)]. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible. Ignored nodes: comments, script, style <body> <div> <div class="Toastify" /> <div> <form class="studioFileUploader" > <input accept=".json" class="fileInput" type="file" /> <button class="fds-btn fds-focus fds-btn--sm fds-btn--tertiary fds-btn--first studioButton small" type="button" > <span class="innerContainer" > <span aria-hidden="true" class="iconWrapper" > <svg fill="none" focusable="false" height="1em" role="img" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" > <path clip-rule="evenodd" d="M6.97 9.03a.75.75 0 0 0 1.06 0l3.22-3.22v8.69a.75.75 0 0 0 1.5 0V5.81l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 0 1.06M4.75 15.5a.75.75 0 0 0-1.5 0V19c0 .966.784 1.75 1.75 1.75h14A1.75 1.75 0 0 0 20.75 19v-3.5a.75.75 0 0 0-1.5 0V19a.25.25 0 0 1-.25.25H5a.25.25 0 0 1-.25-.25z" fill="currentColor" fill-rule="evenodd" /> </svg> </span> [mockedText(ux_editor.modal_properties_code_list_upload)] </span> </button> </form> <p> [mockedText(ux_editor.modal_properties_code_list_read_more_static)] </p> </div> </div> </body> at waitForWrapper (../node_modules/@testing-library/dom/dist/wait-for.js:163:27) at ../node_modules/@testing-library/dom/dist/query-helpers.js:86:33 at Object.findByText (packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx:49:20)
).toBeInTheDocument();
});

Expand Down Expand Up @@ -130,6 +131,58 @@
await screen.findByText(textMock('ux_editor.modal_properties_error_message')),
).toBeInTheDocument();
});

it('should render success toast if file upload is successful', async () => {
const user = userEvent.setup();
const file = new File(['hello'], 'hello.json', { type: 'text/json' });
await render({
queries: {
getOptionListIds: jest
.fn()
.mockImplementation(() => Promise.resolve<string[]>(optionListIdsMock)),
},
});

const btn = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_upload'),
});
await user.click(btn);

const fileInput = screen.getByTestId(fileSelectorInputId);

Check failure on line 151 in frontend/packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx

View workflow job for this annotation

GitHub Actions / Testing

EditCodeList › should render success toast if file upload is successful

TestingLibraryElementError: Unable to find an element by: [data-testid="file-selector-input"] Ignored nodes: comments, script, style <body> <div> <div class="Toastify" /> <div> <div> <div> <div class="formField" > <div class="fds-paragraph fds-paragraph--md fds-native-select--container" > <select class="fds-native-select fds-native-select--md fds-focus" id=":ro:" > <option hidden="" value="" > [mockedText(ux_editor.modal_properties_code_list_helper)] </option> <option value="test-1" > test-1 </option> <option value="test-2" > test-2 </option> </select> </div> </div> </div> </div> <form class="studioFileUploader" > <input accept=".json" class="fileInput" type="file" /> <button class="fds-btn fds-focus fds-btn--sm fds-btn--tertiary fds-btn--first studioButton small" type="button" > <span class="innerContainer" > <span aria-hidden="true" class="iconWrapper" > <svg fill="none" focusable="false" height="1em" role="img" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" > <path clip-rule="evenodd" d="M6.97 9.03a.75.75 0 0 0 1.06 0l3.22-3.22v8.69a.75.75 0 0 0 1.5 0V5.81l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 0 1.06M4.75 15.5a.75.75 0 0 0-1.5 0V19c0 .966.784 1.75 1.75 1.75h14A1.75 1.75 0 0 0 20.75 19v-3.5a.75.75 0 0 0-1.5 0V19a.25.25 0 0 1-.25.25H5a.25.25 0 0 1-.25-.25z" fill="currentColor" fill-rule="evenodd" /> </svg> </span> [mockedText(ux_editor.modal_properties_code_list_upload)] </span> </button> </form> <p> [mockedText(ux_editor.modal_properties_code_list_read_more_static)] </p> </div> </div> </body> at Object.getElementError (../node_modules/@testing-library/dom/dist/config.js:37:19) at ../node_modules/@testing-library/dom/dist/query-helpers.js:76:38 at ../node_modules/@testing-library/dom/dist/query-helpers.js:52:17 at ../node_modules/@testing-library/dom/dist/query-helpers.js:95:19 at Object.getByTestId (packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx:151:30)

await user.upload(fileInput, file);

expect(await screen.findByRole('alert')).toHaveTextContent(
textMock('ux_editor.modal_properties_code_list_upload_success'),
);
});

it('should render error toast if file already exists', async () => {
const user = userEvent.setup();
const file = new File([optionListIdsMock[0]], optionListIdsMock[0] + '.json', {
type: 'text/json',
});
await render({
queries: {
getOptionListIds: jest
.fn()
.mockImplementation(() => Promise.resolve<string[]>(optionListIdsMock)),
},
});

const btn = screen.getByRole('button', {
name: textMock('ux_editor.modal_properties_code_list_upload'),
});
await user.click(btn);

const fileInput = screen.getByTestId(fileSelectorInputId);

Check failure on line 178 in frontend/packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx

View workflow job for this annotation

GitHub Actions / Testing

EditCodeList › should render error toast if file already exists

TestingLibraryElementError: Unable to find an element by: [data-testid="file-selector-input"] Ignored nodes: comments, script, style <body> <div> <div class="Toastify" /> <div> <div> <div> <div class="formField" > <div class="fds-paragraph fds-paragraph--md fds-native-select--container" > <select class="fds-native-select fds-native-select--md fds-focus" id=":rs:" > <option hidden="" value="" > [mockedText(ux_editor.modal_properties_code_list_helper)] </option> <option value="test-1" > test-1 </option> <option value="test-2" > test-2 </option> </select> </div> </div> </div> </div> <form class="studioFileUploader" > <input accept=".json" class="fileInput" type="file" /> <button class="fds-btn fds-focus fds-btn--sm fds-btn--tertiary fds-btn--first studioButton small" type="button" > <span class="innerContainer" > <span aria-hidden="true" class="iconWrapper" > <svg fill="none" focusable="false" height="1em" role="img" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" > <path clip-rule="evenodd" d="M6.97 9.03a.75.75 0 0 0 1.06 0l3.22-3.22v8.69a.75.75 0 0 0 1.5 0V5.81l3.22 3.22a.75.75 0 1 0 1.06-1.06l-4.5-4.5a.75.75 0 0 0-1.06 0l-4.5 4.5a.75.75 0 0 0 0 1.06M4.75 15.5a.75.75 0 0 0-1.5 0V19c0 .966.784 1.75 1.75 1.75h14A1.75 1.75 0 0 0 20.75 19v-3.5a.75.75 0 0 0-1.5 0V19a.25.25 0 0 1-.25.25H5a.25.25 0 0 1-.25-.25z" fill="currentColor" fill-rule="evenodd" /> </svg> </span> [mockedText(ux_editor.modal_properties_code_list_upload)] </span> </button> </form> <p> [mockedText(ux_editor.modal_properties_code_list_read_more_static)] </p> </div> </div> </body> at Object.getElementError (../node_modules/@testing-library/dom/dist/config.js:37:19) at ../node_modules/@testing-library/dom/dist/query-helpers.js:76:38 at ../node_modules/@testing-library/dom/dist/query-helpers.js:52:17 at ../node_modules/@testing-library/dom/dist/query-helpers.js:95:19 at Object.getByTestId (packages/ux-editor/src/components/config/editModal/EditOptions/EditCodeList/EditCodeList.test.tsx:178:30)

await user.upload(fileInput, file);

expect(await screen.findByRole('alert')).toHaveTextContent(
textMock('ux_editor.modal_properties_code_list_upload_duplicate_error'),
);
});
});

const render = async ({
Expand Down
Loading
Loading