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(dashboard): Improve validation for missing permissions when creating new app #14395

Merged
merged 20 commits into from
Jan 27, 2025
Merged
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
typecheck errors
framitdavid committed Jan 9, 2025
commit 92ff3945fd39f1e67af11ea60cccc702089f145a
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@ import { type Organization } from 'app-shared/types/Organization';
import userEvent from '@testing-library/user-event';
import { textMock } from '@studio/testing/mocks/i18nMock';
import type { ServicesContextProps } from 'app-shared/contexts/ServicesContext';
import { ServicesContextProvider } from 'app-shared/contexts/ServicesContext';
import { renderWithProviders } from '../../testing/mocks';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { useUserOrgPermissionQuery } from '../../hooks/queries/useUserOrgPermissionsQuery';
@@ -144,9 +143,7 @@ function renderNewApplicationForm(
services?: Partial<ServicesContextProps>,
) {
return renderWithProviders(
<ServicesContextProvider>
<NewApplicationForm {...defaultProps} {...newApplicationFormProps} />
</ServicesContextProvider>,
<NewApplicationForm {...defaultProps} {...newApplicationFormProps} />,
{
queries: services,
queryClient: createQueryClientMock(),

Unchanged files with check annotations Beta

/// </summary>
/// <param name="giteaWrapper">the gitea wrapper</param>
/// <param name="antiforgery">Access to the antiforgery system in .NET Core</param>
public UserController(IGitea giteaWrapper, IAntiforgery antiforgery, IUserService userService)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run integration tests against actual gitea and db

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run integration tests against actual gitea and db

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (ubuntu-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (ubuntu-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Analyze

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Analyze

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (windows-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (windows-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (macos-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)

Check warning on line 28 in backend/src/Designer/Controllers/UserController.cs

GitHub Actions / Run dotnet build and test (macos-latest)

Parameter 'userService' has no matching param tag in the XML comment for 'UserController.UserController(IGitea, IAntiforgery, IUserService)' (but other parameters do)
{
_giteaApi = giteaWrapper;
_antiforgery = antiforgery;
await user.click(createBtn);
const emptyFieldErrors = await screen.findAllByText(

Check failure on line 83 in frontend/dashboard/pages/CreateService/CreateService.test.tsx

GitHub Actions / Testing

CreateService › should show error messages when clicking create and no owner or name is filled in

Unable to find an element with the text: [mockedText(dashboard.field_cannot_be_empty)]. 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 class="wrapper" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":r0:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:r1:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":r0:" name="org" > <option selected="" value="" /> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:r1:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20" type="text" value="" /> </div> <div aria-live="polite" aria-relevant="additions removals" class="fds-textfield__error-message" id="textfield-error-:r2:" /> </div> <p class="fds-paragraph fds-paragraph--sm textWrapper" > [mockedText(dashboard.service_saved_name_description)] <strong style="font-weight: 500;" > [mockedText(dashboard.service_saved_name_description_cannot_be_changed)] </strong> </p> </div> <div class="actionContainer" > <button class="fds-btn fds-focus fds-btn--sm fds-btn--primary fds-btn--first studioButton" disabled="" type="submit" > [mockedText(dashboard.create_service_btn)] </button> <a href="/none" > [mockedText(general.cancel)] </a> </div> </form> </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.findAllByText (dashboard/pages/CreateService/CreateService.test.tsx:83:43)
textMock('dashboard.field_cannot_be_empty'),
);
expect(emptyFieldErrors.length).toBe(2);
expect(addRepoMock).rejects.toEqual({ response: { status: 409 } });
await screen.findByText(textMock('dashboard.app_already_exists'));

Check failure on line 184 in frontend/dashboard/pages/CreateService/CreateService.test.tsx

GitHub Actions / Testing

CreateService › should show error message that app already exists when trying to create an app with a name that already exists

Unable to find an element with the text: [mockedText(dashboard.app_already_exists)]. 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 class="wrapper" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":rk:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:rl:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":rk:" name="org" > <option selected="" value="test" > test </option> <option value="unit-test" > unit-test </option> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:rl:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20" type="text" value="" /> </div> <div aria-live="polite" aria-relevant="additions removals" class="fds-textfield__error-message" id="textfield-error-:rm:" /> </div> <p class="fds-paragraph fds-paragraph--sm textWrapper" > [mockedText(dashboard.service_saved_name_description)] <strong style="font-weight: 500;" > [mockedText(dashboard.service_saved_name_description_cannot_be_changed)] </strong> </p> </div> <div class="actionContainer" > <button class="fds-btn fds-focus fds-btn--sm fds-btn--primary fds-btn--first studioButton" disabled="" type="submit" > [mockedText(dashboard.create_service_btn)] </button> <a href="/none" > [mockedText(general.cancel)] </a> </div> </form> </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 (dashboard/pages/CreateService/CreateService.test.tsx:184:18)
});
it('should show generic error message when trying to create an app and something unknown went wrong', async () => {
await expect(addRepoMock).rejects.toEqual({ response: { status: 500 } });
const emptyFieldErrors = await screen.findAllByText(textMock('general.error_message'));

Check failure on line 204 in frontend/dashboard/pages/CreateService/CreateService.test.tsx

GitHub Actions / Testing

CreateService › should show generic error message when trying to create an app and something unknown went wrong

Unable to find an element with the text: [mockedText(general.error_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 class="wrapper" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":ro:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:rp:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":ro:" name="org" > <option selected="" value="test" > test </option> <option value="unit-test" > unit-test </option> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:rp:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20" type="text" value="" /> </div> <div aria-live="polite" aria-relevant="additions removals" class="fds-textfield__error-message" id="textfield-error-:rq:" /> </div> <p class="fds-paragraph fds-paragraph--sm textWrapper" > [mockedText(dashboard.service_saved_name_description)] <strong style="font-weight: 500;" > [mockedText(dashboard.service_saved_name_description_cannot_be_changed)] </strong> </p> </div> <div class="actionContainer" > <button class="fds-btn fds-focus fds-btn--sm fds-btn--primary fds-btn--first studioButton" disabled="" type="submit" > [mockedText(dashboard.create_service_btn)] </button> <a href="/none" > [mockedText(general.cancel)] </a> </div> </form> </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.findAllByText (dashboard/pages/CreateService/CreateService.test.tsx:204:43)
expect(emptyFieldErrors.length).toBe(1);
});
await user.type(appNameInput, 'appname');
await user.click(createBtn);
expect(await screen.findByText(textMock('dashboard.creating_your_service')));

Check failure on line 240 in frontend/dashboard/pages/CreateService/CreateService.test.tsx

GitHub Actions / Testing

CreateService › should display loading while the form is processing

Unable to find an element with the text: [mockedText(dashboard.creating_your_service)]. 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 class="wrapper" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":rs:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:rt:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":rs:" name="org" > <option selected="" value="tester" > tester </option> <option value="unit-test" > unit-test </option> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:rt:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20" type="text" value="" /> </div> <div aria-live="polite" aria-relevant="additions removals" class="fds-textfield__error-message" id="textfield-error-:ru:" /> </div> <p class="fds-paragraph fds-paragraph--sm textWrapper" > [mockedText(dashboard.service_saved_name_description)] <strong style="font-weight: 500;" > [mockedText(dashboard.service_saved_name_description_cannot_be_changed)] </strong> </p> </div> <div class="actionContainer" > <button class="fds-btn fds-focus fds-btn--sm fds-btn--primary fds-btn--first studioButton" disabled="" type="submit" > [mockedText(dashboard.create_service_btn)] </button> <a href="/none" > [mockedText(general.cancel)] </a> </div> </form> </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 (dashboard/pages/CreateService/CreateService.test.tsx:240:25)
});
it('should not display loading if process form fails, should display create and cancel button', async () => {
await user.type(appNameInput, 'appname');
await user.click(createBtn);
expect(windowLocationAssignMock).toHaveBeenCalled();

Check failure on line 297 in frontend/dashboard/pages/CreateService/CreateService.test.tsx

GitHub Actions / Testing

CreateService › should navigate to app-development if creating the app was successful

expect(jest.fn()).toHaveBeenCalled() Expected number of calls: >= 1 Received number of calls: 0 at Object.toHaveBeenCalled (dashboard/pages/CreateService/CreateService.test.tsx:297:38)
});
it('should set cancel link to / when selected context is self', async () => {
const copyButton = screen.getByRole('button', { name: textMock('dashboard.make_copy') });
await user.click(copyButton);
expect(queriesMock.copyApp).toHaveBeenCalledTimes(1);

Check failure on line 81 in frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx

GitHub Actions / Testing

MakeCopyModal › successfully adds the values and submits the copy of a new application

expect(jest.fn()).toHaveBeenCalledTimes(expected) Expected number of calls: 1 Received number of calls: 0 at Object.toHaveBeenCalledTimes (dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx:81:33)
expect(queriesMock.copyApp).toHaveBeenCalledWith(org, app, newRepoValue, mockUser.login);
});
name: textMock('dashboard.make_copy'),
});
await user.click(confirmButton);
const errorMessageElement = screen.getAllByText(textMock('dashboard.field_cannot_be_empty'));

Check failure on line 93 in frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx

GitHub Actions / Testing

MakeCopyModal › should show error message when clicking confirm without adding name

TestingLibraryElementError: Unable to find an element with the text: [mockedText(dashboard.field_cannot_be_empty)]. 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 class="fds-modal--lock-scroll" > <div> <div class="Toastify" /> <dialog class="fds-modal dialog withContentPadding" open="" > <span data-floating-ui-focus-guard="" data-type="inside" role="button" style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;" tabindex="0" /> <div class="fds-modal__header heading" > <h2 class="fds-heading fds-heading--xs" > <span> [mockedText(dashboard.copy_application)] </span> </h2> <button class="fds-btn fds-focus fds-btn--md fds-btn--tertiary fds-btn--second fds-btn--icon-only fds-modal__header__button" name="close" type="button" > <svg aria-labelledby="title-r7" fill="none" focusable="false" font-size="1.5em" height="1em" role="img" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" > <title id="title-r7" > close modal </title> <path d="M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94 6.53 5.47Z" fill="currentColor" /> </svg> </button> </div> <div class="fds-modal__content content" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":r8:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:r9:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":r8:" name="org" > <option selected="" value="test" > Test Tester </option> <option value="unit-test" > unit-test </option> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:r9:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20"
expect(errorMessageElement.length).toBeGreaterThan(0);
});
const copyButton = screen.getByRole('button', { name: textMock('dashboard.make_copy') });
await user.click(copyButton);
expect(mockNavigateToPackage).toHaveBeenCalled();

Check failure on line 144 in frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx

GitHub Actions / Testing

MakeCopyModal › navigates to the correct url when the app is copied

expect(jest.fn()).toHaveBeenCalled() Expected number of calls: >= 1 Received number of calls: 0 at Object.toHaveBeenCalled (dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx:144:35)
});
it('should show error message that app already exists when trying to copy an app with a name that already exists', async () => {
expect(copyRepoMock).rejects.toEqual({ response: { status: 409 } });
await screen.findByText(textMock('dashboard.app_already_exists'));

Check failure on line 164 in frontend/dashboard/components/MakeCopyModal/MakeCopyModal.test.tsx

GitHub Actions / Testing

MakeCopyModal › should show error message that app already exists when trying to copy an app with a name that already exists

Unable to find an element with the text: [mockedText(dashboard.app_already_exists)]. 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 class="fds-modal--lock-scroll" > <div> <div class="Toastify" /> <dialog class="fds-modal dialog withContentPadding" open="" > <span data-floating-ui-focus-guard="" data-type="inside" role="button" style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: fixed; white-space: nowrap; width: 1px; top: 0px; left: 0px;" tabindex="0" /> <div class="fds-modal__header heading" > <h2 class="fds-heading fds-heading--xs" > <span> [mockedText(dashboard.copy_application)] </span> </h2> <button class="fds-btn fds-focus fds-btn--md fds-btn--tertiary fds-btn--second fds-btn--icon-only fds-modal__header__button" name="close" type="button" > <svg aria-labelledby="title-rv" fill="none" focusable="false" font-size="1.5em" height="1em" role="img" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" > <title id="title-rv" > close modal </title> <path d="M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94 6.53 5.47Z" fill="currentColor" /> </svg> </button> </div> <div class="fds-modal__content content" > <form class="form" > <div class="fds-paragraph fds-paragraph--sm fds-native-select--container fds-native-select--error" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-native-select__label" for=":r10:" > [mockedText(general.service_owner)] </label> <select aria-describedby="select-error-:r11:" aria-invalid="true" class="fds-native-select fds-native-select--sm fds-focus" id=":r10:" name="org" > <option selected="" value="test" > Test Tester </option> <option value="unit-test" > unit-test </option> </select> <div aria-live="polite" aria-relevant="additions removals" class="fds-native-select__error-message" id="select-error-:r11:" > <div class="fds-error-message fds-error-message--sm fds-error-message--error" > [mockedText(dashboard.missing_service_owner_rights_error_message)] </div> </div> </div> <div> <div class="fds-paragraph fds-paragraph--sm fds-textfield fds-textfield--sm" > <label class="fds-label fds-label--sm fds-label--medium-weight fds-textfield__label" for="service-saved-name" > <span> [mockedText(general.service_name)] </span> </label> <div class="fds-textfield__field" > <input class="fds-textfield__input fds-focus" id="service-saved-name" name="repoName" size="20" type="text"
});
it('closes the modal when the close button is clicked', async () => {