diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index 315a0d94dd..594b9e2ddd 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -31,6 +31,7 @@ import { FirstLoginPageComponent } from '@features/first-login-page/first-login-
import { ForgotYourPasswordComponent } from '@features/forgot-your-username-or-password/forgot-your-password/forgot-your-password.component';
import { ForgotYourUsernameOrPasswordComponent } from '@features/forgot-your-username-or-password/forgot-your-username-or-password.component';
import { ForgotYourUsernameComponent } from '@features/forgot-your-username-or-password/forgot-your-username/forgot-your-username.component';
+import { UsernameFoundComponent } from '@features/forgot-your-username-or-password/username-found/username-found.component';
import { LoginComponent } from '@features/login/login.component';
import { LogoutComponent } from '@features/logout/logout.component';
import { MigratedUserTermsConditionsComponent } from '@features/migrated-user-terms-conditions/migrated-user-terms-conditions.component';
@@ -111,6 +112,11 @@ const routes: Routes = [
component: SatisfactionSurveyComponent,
data: { title: 'Satisfaction Survey' },
},
+ {
+ path: 'username-found',
+ component: UsernameFoundComponent,
+ data: { title: 'Username Found' },
+ },
],
},
{
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 3e5cf82cda..86c33d5b6b 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -97,6 +97,7 @@ import { SharedModule } from '@shared/shared.module';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SentryErrorHandler } from './SentryErrorHandler.component';
+import { UsernameFoundComponent } from '@features/forgot-your-username-or-password/username-found/username-found.component';
@NgModule({
declarations: [
@@ -139,6 +140,7 @@ import { SentryErrorHandler } from './SentryErrorHandler.component';
ParentWorkplaceAccounts,
DeleteWorkplaceComponent,
ForgotYourUsernameOrPasswordComponent,
+ UsernameFoundComponent,
ForgotYourUsernameComponent,
FindAccountComponent,
FindUsernameComponent,
diff --git a/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.html b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.html
new file mode 100644
index 0000000000..258f2ae594
--- /dev/null
+++ b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.html
@@ -0,0 +1,7 @@
+
+
+
Page no longer available
+
The page you are trying to view does not exist anymore.
+
Return to the homepage
+
+
diff --git a/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.spec.ts b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.spec.ts
new file mode 100644
index 0000000000..a43de9798d
--- /dev/null
+++ b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.spec.ts
@@ -0,0 +1,41 @@
+import { render } from '@testing-library/angular';
+import { RouterModule } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { PageNoLongerAvailableComponent } from './page-no-longer-available.component';
+
+describe('PageNoLongerAvailableComponent', () => {
+ const setup = async () => {
+ const setupTools = await render(PageNoLongerAvailableComponent, {
+ imports: [RouterModule, RouterTestingModule, HttpClientTestingModule],
+ declarations: [],
+ providers: [],
+ componentProperties: {},
+ });
+
+ const component = setupTools.fixture.componentInstance;
+
+ return { ...setupTools, component };
+ };
+
+ it('should create', async () => {
+ const { component } = await setup();
+
+ expect(component).toBeTruthy();
+ });
+
+ it('should show the page heading', async () => {
+ const { getByRole } = await setup();
+
+ expect(getByRole('heading', { name: 'Page no longer available' })).toBeTruthy();
+ });
+
+ it('should show a link to the homepage', async () => {
+ const { getByText } = await setup();
+
+ const linkText = getByText('Return to the homepage');
+
+ expect(linkText).toBeTruthy();
+ expect(linkText.getAttribute('href')).toEqual('/login');
+ });
+});
diff --git a/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.ts b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.ts
new file mode 100644
index 0000000000..ad7a1e020c
--- /dev/null
+++ b/frontend/src/app/core/components/error/page-no-longer-available/page-no-longer-available.component.ts
@@ -0,0 +1,9 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-page-no-longer-available',
+ templateUrl: './page-no-longer-available.component.html',
+})
+export class PageNoLongerAvailableComponent {
+ constructor() {}
+}
diff --git a/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.html b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.html
new file mode 100644
index 0000000000..59ecc0d729
--- /dev/null
+++ b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.html
@@ -0,0 +1,28 @@
+
+
+
+ We’ve found your username
+
+
+ Your username is
+
{{ username }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.scss b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.scss
new file mode 100644
index 0000000000..3296d00f22
--- /dev/null
+++ b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.scss
@@ -0,0 +1,8 @@
+.panel {
+ width: 64%;
+}
+
+.green-tick-icon {
+ height: 28px;
+ vertical-align: baseline;
+}
diff --git a/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.spec.ts b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.spec.ts
new file mode 100644
index 0000000000..ebb4af802e
--- /dev/null
+++ b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.spec.ts
@@ -0,0 +1,94 @@
+import { fireEvent, render, within } from '@testing-library/angular';
+import { UsernameFoundComponent } from './username-found.component';
+import { getTestBed } from '@angular/core/testing';
+import { Router, RouterModule } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { FindUsernameService } from '@core/services/find-username.service';
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { PageNoLongerAvailableComponent } from '@core/components/error/page-no-longer-available/page-no-longer-available.component';
+
+describe('UsernameFoundComponent', () => {
+ const setup = async (overrides: any = {}) => {
+ const setupTools = await render(UsernameFoundComponent, {
+ imports: [RouterModule, RouterTestingModule, HttpClientTestingModule],
+ declarations: [PageNoLongerAvailableComponent],
+ providers: [
+ {
+ provide: FindUsernameService,
+ useValue: { usernameFound: overrides.username },
+ },
+ ],
+ componentProperties: {},
+ });
+
+ const component = setupTools.fixture.componentInstance;
+
+ const injector = getTestBed();
+ const router = injector.inject(Router) as Router;
+
+ const routerSpy = spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
+
+ return { ...setupTools, component, routerSpy };
+ };
+
+ it('should create UsernameFoundComponent', async () => {
+ const overrides = {
+ username: 'Bighitterhank1000',
+ };
+
+ const { component } = await setup(overrides);
+
+ expect(component).toBeTruthy();
+ });
+
+ it('should show the panel', async () => {
+ const overrides = {
+ username: 'Bighitterhank1000',
+ };
+
+ const { getByTestId } = await setup(overrides);
+
+ const panel = getByTestId('panel');
+
+ expect(panel).toBeTruthy();
+ expect(within(panel).getByText('We’ve found your username'));
+ });
+
+ it('should show the username', async () => {
+ const overrides = {
+ username: 'Bighitterhank1000',
+ };
+
+ const { getByTestId } = await setup(overrides);
+
+ const panel = getByTestId('panel');
+ expect(within(panel).getByText('Your username is'));
+ expect(within(panel).getByText('Bighitterhank1000'));
+ });
+
+ it('should go back to the sign in page when the button is clicked', async () => {
+ const overrides = {
+ username: 'Bighitterhank1000',
+ };
+
+ const { fixture, getByText, routerSpy } = await setup(overrides);
+
+ const buttonText = getByText('Back to sign in');
+ expect(buttonText).toBeTruthy();
+
+ fireEvent.click(buttonText);
+ fixture.detectChanges();
+
+ expect(routerSpy).toHaveBeenCalledWith(['/login']);
+ });
+
+ it('should show page no longer available if no username was found', async () => {
+ const overrides = {
+ username: null,
+ };
+
+ const { getByTestId } = await setup(overrides);
+
+ expect(getByTestId('page-no-longer-available')).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.ts b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.ts
new file mode 100644
index 0000000000..7d5ea43b71
--- /dev/null
+++ b/frontend/src/app/features/forgot-your-username-or-password/username-found/username-found.component.ts
@@ -0,0 +1,29 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { FindUsernameService } from '@core/services/find-username.service';
+
+@Component({
+ selector: 'app-username-found',
+ templateUrl: './username-found.component.html',
+ styleUrls: ['./username-found.component.scss'],
+})
+export class UsernameFoundComponent implements OnInit {
+ public username: string;
+ public isUsernameFound: boolean;
+
+ constructor(private router: Router, private findUsernameService: FindUsernameService) {}
+
+ ngOnInit(): void {
+ this.getUsernameFound();
+ this.isUsernameFound = this.username !== null;
+ }
+
+ public getUsernameFound(): void {
+ this.username = this.findUsernameService.usernameFound;
+ }
+
+ public backToSignInPage(event: Event): void {
+ event.preventDefault();
+ this.router.navigate(['/login']);
+ }
+}
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts
index cf32a1c4ab..54c3df794b 100644
--- a/frontend/src/app/shared/shared.module.ts
+++ b/frontend/src/app/shared/shared.module.ts
@@ -5,20 +5,15 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { CannotCreateAccountComponent } from '@core/components/error/cannot-create-account/cannot-create-account.component';
import { PageNotFoundComponent } from '@core/components/error/page-not-found/page-not-found.component';
+import { PageNoLongerAvailableComponent } from '@core/components/error/page-no-longer-available/page-no-longer-available.component';
import { ArticleListResolver } from '@core/resolvers/article-list.resolver';
import { PageResolver } from '@core/resolvers/page.resolver';
import { DialogService } from '@core/services/dialog.service';
import { ArticleListComponent } from '@features/articles/article-list/article-list.component';
import { NewArticleListComponent } from '@features/articles/new-article-list/new-article-list.component';
-import {
- NewTrainingLinkPanelComponent,
-} from '@features/new-dashboard/training-tab/training-link-panel/training-link-panel.component';
-import {
- MissingMandatoryTrainingComponent,
-} from '@features/training-and-qualifications/new-training-qualifications-record/missing-mandatory-training/missing-mandatory-training.component';
-import {
- DeleteWorkplaceDialogComponent,
-} from '@features/workplace/delete-workplace-dialog/delete-workplace-dialog.component';
+import { NewTrainingLinkPanelComponent } from '@features/new-dashboard/training-tab/training-link-panel/training-link-panel.component';
+import { MissingMandatoryTrainingComponent } from '@features/training-and-qualifications/new-training-qualifications-record/missing-mandatory-training/missing-mandatory-training.component';
+import { DeleteWorkplaceDialogComponent } from '@features/workplace/delete-workplace-dialog/delete-workplace-dialog.component';
import { AlertComponent } from '@shared/components/alert/alert.component';
import { CheckCQCDetailsComponent } from '@shared/components/check-cqc-details/check-cqc-details.component';
import { NewDashboardHeaderComponent } from '@shared/components/new-dashboard-header/dashboard-header.component';
@@ -27,12 +22,8 @@ import { WorkplaceTabComponent } from '@shared/components/workplace-tab/workplac
import { BulkUploadFileTypePipePipe } from '@shared/pipes/bulk-upload-file-type.pipe';
import { SanitizeVideoUrlPipe } from '@shared/pipes/sanitize-video-url.pipe';
-import {
- GroupedRadioButtonAccordionComponent,
-} from './components/accordions/radio-button-accordion/grouped-radio-button-accordion/grouped-radio-button-accordion.component';
-import {
- RadioButtonAccordionComponent,
-} from './components/accordions/radio-button-accordion/radio-button-accordion.component';
+import { GroupedRadioButtonAccordionComponent } from './components/accordions/radio-button-accordion/grouped-radio-button-accordion/grouped-radio-button-accordion.component';
+import { RadioButtonAccordionComponent } from './components/accordions/radio-button-accordion/radio-button-accordion.component';
import { AddNoteComponent } from './components/add-note/add-note.component';
import { AutoSuggestComponent } from './components/auto-suggest/auto-suggest.component';
import { BackLinkComponent } from './components/back-link/back-link.component';
@@ -46,66 +37,44 @@ import { CharacterCountComponent } from './components/character-count/character-
import { AboutTheDataLinkComponent } from './components/data-area-tab/about-the-data-link/about-the-data-link.component';
import { DatePickerComponent } from './components/date-picker/date-picker.component';
import { DetailsComponent } from './components/details/details.component';
-import {
- ValidationErrorMessageComponent,
-} from './components/drag-and-drop/validation-error-message/validation-error-message.component';
+import { ValidationErrorMessageComponent } from './components/drag-and-drop/validation-error-message/validation-error-message.component';
import { EligibilityIconComponent } from './components/eligibility-icon/eligibility-icon.component';
import { ErrorSummaryComponent } from './components/error-summary/error-summary.component';
import { InsetTextComponent } from './components/inset-text/inset-text.component';
-import {
- LinkToParentCancelDialogComponent,
-} from './components/link-to-parent-cancel/link-to-parent-cancel-dialog.component';
-import {
- LinkToParentRemoveDialogComponent,
-} from './components/link-to-parent-remove/link-to-parent-remove-dialog.component';
+import { LinkToParentCancelDialogComponent } from './components/link-to-parent-cancel/link-to-parent-cancel-dialog.component';
+import { LinkToParentRemoveDialogComponent } from './components/link-to-parent-remove/link-to-parent-remove-dialog.component';
import { LinkToParentDialogComponent } from './components/link-to-parent/link-to-parent-dialog.component';
import { LinkWithArrowComponent } from './components/link-with-arrow/link-with-arrow.component';
import { MessagesComponent } from './components/messages/messages.component';
import { MoveWorkplaceDialogComponent } from './components/move-workplace/move-workplace-dialog.component';
-import {
- NavigateToWorkplaceDropdownComponent,
-} from './components/navigate-to-workplace-dropdown/navigate-to-workplace-dropdown.component';
+import { NavigateToWorkplaceDropdownComponent } from './components/navigate-to-workplace-dropdown/navigate-to-workplace-dropdown.component';
import { NewBackLinkComponent } from './components/new-back-link/new-back-link.component';
import { NewTabsComponent } from './components/new-tabs/new-tabs.component';
import { WDFTabComponent } from './components/new-wdf-tabs/new-wdf-tab.component';
import { WDFWorkplaceSummaryComponent } from './components/new-wdf-workplace-summary/wdf-workplace-summary.component';
import { NewWorkplaceSummaryComponent } from './components/new-workplace-summary/workplace-summary.component';
import { OtherLinksComponent } from './components/other-links/other-links.component';
-import {
- OwnershipChangeMessageDialogComponent,
-} from './components/ownership-change-message/ownership-change-message-dialog.component';
+import { OwnershipChangeMessageDialogComponent } from './components/ownership-change-message/ownership-change-message-dialog.component';
import { PageComponent } from './components/page/page.component';
import { PaginationComponent } from './components/pagination/pagination.component';
import { PanelComponent } from './components/panel/panel.component';
import { PhaseBannerComponent } from './components/phase-banner/phase-banner.component';
import { ProgressBarComponent } from './components/progress-bar/progress-bar.component';
import { ProgressComponent } from './components/progress/progress.component';
-import {
- RegistrationSubmitButtonsComponent,
-} from './components/registration-submit-buttons/registration-submit-buttons.component';
+import { RegistrationSubmitButtonsComponent } from './components/registration-submit-buttons/registration-submit-buttons.component';
import { RejectRequestDialogComponent } from './components/reject-request-dialog/reject-request-dialog.component';
-import {
- RemoveParentConfirmationComponent,
-} from './components/remove-parent-confirmation/remove-parent-confirmation.component';
+import { RemoveParentConfirmationComponent } from './components/remove-parent-confirmation/remove-parent-confirmation.component';
import { ReviewCheckboxComponent } from './components/review-checkbox/review-checkbox.component';
import { SearchInputComponent } from './components/search-input/search-input.component';
-import {
- SelectUploadCertificateComponent,
-} from './components/select-upload-certificate/select-upload-certificate.component';
+import { SelectUploadCertificateComponent } from './components/select-upload-certificate/select-upload-certificate.component';
import { SelectUploadFileComponent } from './components/select-upload-file/select-upload-file.component';
-import {
- SelectWorkplaceDropdownFormComponent,
-} from './components/select-workplace-dropdown-form/select-workplace-dropdown-form.component';
-import {
- SelectWorkplaceRadioButtonFormComponent,
-} from './components/select-workplace-radio-button-form/select-workplace-radio-button-form.component';
+import { SelectWorkplaceDropdownFormComponent } from './components/select-workplace-dropdown-form/select-workplace-dropdown-form.component';
+import { SelectWorkplaceRadioButtonFormComponent } from './components/select-workplace-radio-button-form/select-workplace-radio-button-form.component';
import { SetDataPermissionDialogComponent } from './components/set-data-permission/set-data-permission-dialog.component';
import { BasicRecordComponent } from './components/staff-record-summary/basic-record/basic-record.component';
import { EmploymentComponent } from './components/staff-record-summary/employment/employment.component';
import { PersonalDetailsComponent } from './components/staff-record-summary/personal-details/personal-details.component';
-import {
- QualificationsAndTrainingComponent,
-} from './components/staff-record-summary/qualifications-and-training/qualifications-and-training.component';
+import { QualificationsAndTrainingComponent } from './components/staff-record-summary/qualifications-and-training/qualifications-and-training.component';
import { StaffRecordSummaryComponent } from './components/staff-record-summary/staff-record-summary.component';
import { StaffRecordsTabComponent } from './components/staff-records-tab/staff-records-tab.component';
import { StaffSummaryComponent } from './components/staff-summary/staff-summary.component';
@@ -120,35 +89,21 @@ import { TabComponent } from './components/tabs/tab.component';
import { TabsComponent } from './components/tabs/tabs.component';
import { TotalStaffPanelComponent } from './components/total-staff-panel/total-staff-panel.component';
import { TotalStaffComponent } from './components/total-staff/total-staff.component';
-import {
- TrainingAndQualificationsCategoriesComponent,
-} from './components/training-and-qualifications-categories/training-and-qualifications-categories.component';
-import {
- ViewTrainingComponent,
-} from './components/training-and-qualifications-categories/view-trainings/view-trainings.component';
-import {
- TrainingAndQualificationsSummaryComponent,
-} from './components/training-and-qualifications-summary/training-and-qualifications-summary.component';
-import {
- TrainingAndQualificationsTabComponent,
-} from './components/training-and-qualifications-tab/training-and-qualifications-tab.component';
+import { TrainingAndQualificationsCategoriesComponent } from './components/training-and-qualifications-categories/training-and-qualifications-categories.component';
+import { ViewTrainingComponent } from './components/training-and-qualifications-categories/view-trainings/view-trainings.component';
+import { TrainingAndQualificationsSummaryComponent } from './components/training-and-qualifications-summary/training-and-qualifications-summary.component';
+import { TrainingAndQualificationsTabComponent } from './components/training-and-qualifications-tab/training-and-qualifications-tab.component';
import { TrainingInfoPanelComponent } from './components/training-info-panel/training-info-panel.component';
import { TrainingLinkPanelComponent } from './components/training-link-panel/training-link-panel.component';
-import {
- TrainingSelectViewPanelComponent,
-} from './components/training-select-view-panel/training-select-view-panel.component';
+import { TrainingSelectViewPanelComponent } from './components/training-select-view-panel/training-select-view-panel.component';
import { UserAccountsSummaryComponent } from './components/user-accounts-summary/user-accounts-summary.component';
import { UserFormComponent } from './components/user-form/user-form.component';
import { UserTableComponent } from './components/users-table/user.table.component';
import { WdfConfirmationPanelComponent } from './components/wdf-confirmation-panel/wdf-confirmation-panel.component';
import { WdfFieldConfirmationComponent } from './components/wdf-field-confirmation/wdf-field-confirmation.component';
-import {
- WdfStaffMismatchMessageComponent,
-} from './components/wdf-staff-mismatch-message/wdf-staff-mismatch-message.component';
+import { WdfStaffMismatchMessageComponent } from './components/wdf-staff-mismatch-message/wdf-staff-mismatch-message.component';
import { WdfTabComponent } from './components/wdf-tab/wdf-tab.component';
-import {
- WorkplaceContinueCancelButtonComponent,
-} from './components/workplace-continue-cancel-button.component/workplace-continue-cancel-button.component';
+import { WorkplaceContinueCancelButtonComponent } from './components/workplace-continue-cancel-button.component/workplace-continue-cancel-button.component';
import { WorkplaceSubmitButtonComponent } from './components/workplace-submit-button/workplace-submit-button.component';
import { WorkplaceSummaryComponent } from './components/workplace-summary/workplace-summary.component';
import { FileValueAccessorDirective } from './form-controls/file-control-value-accessor';
@@ -248,6 +203,7 @@ import { WorkplacePermissionsBearerPipe } from './pipes/workplace-permissions-be
WdfStaffMismatchMessageComponent,
CheckCQCDetailsComponent,
PageNotFoundComponent,
+ PageNoLongerAvailableComponent,
ArticleListComponent,
PageComponent,
FirstErrorPipe,
@@ -368,6 +324,7 @@ import { WorkplacePermissionsBearerPipe } from './pipes/workplace-permissions-be
MoveWorkplaceDialogComponent,
CheckCQCDetailsComponent,
PageNotFoundComponent,
+ PageNoLongerAvailableComponent,
ArticleListComponent,
PageComponent,
FirstErrorPipe,