diff --git a/src/app/features/store/pages/reset-password-page/reset-password-page.component.html b/src/app/features/store/pages/reset-password-page/reset-password-page.component.html
index 582aaf6..647d450 100644
--- a/src/app/features/store/pages/reset-password-page/reset-password-page.component.html
+++ b/src/app/features/store/pages/reset-password-page/reset-password-page.component.html
@@ -13,11 +13,13 @@
@if (getControlError('password'); as errorMessage) {
{{ errorMessage }}
@@ -30,11 +32,13 @@
@if (getControlError('password_confirmation'); as errorMessage) {
{{ errorMessage }}
diff --git a/src/app/features/store/pages/reset-password-page/reset-password-page.component.spec.ts b/src/app/features/store/pages/reset-password-page/reset-password-page.component.spec.ts
index fec20c9..636af77 100644
--- a/src/app/features/store/pages/reset-password-page/reset-password-page.component.spec.ts
+++ b/src/app/features/store/pages/reset-password-page/reset-password-page.component.spec.ts
@@ -50,6 +50,43 @@ describe('ResetPasswordPageComponent', () => {
];
}
+ it('shows and hides both password fields with either visibility control', async () => {
+ const modalService = {
+ openSimple: vi.fn(),
+ };
+
+ await TestBed.configureTestingModule({
+ imports: [ResetPasswordPageComponent],
+ providers: resetProviders(modalService),
+ }).compileComponents();
+
+ const fixture = TestBed.createComponent(ResetPasswordPageComponent);
+ fixture.detectChanges();
+
+ const getPasswordInputs = () =>
+ Array.from(fixture.nativeElement.querySelectorAll('input')) as HTMLInputElement[];
+ const getVisibilityButtons = () =>
+ Array.from(
+ fixture.nativeElement.querySelectorAll('button[aria-label]'),
+ ) as HTMLButtonElement[];
+
+ expect(getPasswordInputs().map((input) => input.type)).toEqual(['password', 'password']);
+
+ getVisibilityButtons()[0].click();
+ fixture.detectChanges();
+
+ expect(getPasswordInputs().map((input) => input.type)).toEqual(['text', 'text']);
+ expect(getVisibilityButtons().map((button) => button.getAttribute('aria-label'))).toEqual([
+ 'Ocultar contraseña',
+ 'Ocultar contraseña',
+ ]);
+
+ getVisibilityButtons()[1].click();
+ fixture.detectChanges();
+
+ expect(getPasswordInputs().map((input) => input.type)).toEqual(['password', 'password']);
+ });
+
it('rejects passwords that do not match', async () => {
const modalService = {
openSimple: vi.fn(),
diff --git a/src/app/features/store/pages/reset-password-page/reset-password-page.component.ts b/src/app/features/store/pages/reset-password-page/reset-password-page.component.ts
index eb1fb04..b320af8 100644
--- a/src/app/features/store/pages/reset-password-page/reset-password-page.component.ts
+++ b/src/app/features/store/pages/reset-password-page/reset-password-page.component.ts
@@ -49,6 +49,7 @@ export class ResetPasswordPageComponent {
private readonly submittedState = signal(false);
private readonly isSubmittingState = signal(false);
private readonly serverErrorState = signal(null);
+ private readonly passwordVisibleState = signal(false);
private readonly email = this.route.snapshot.queryParamMap.get('email') ?? '';
private readonly code = this.route.snapshot.queryParamMap.get('code') ?? '';
@@ -72,6 +73,11 @@ export class ResetPasswordPageComponent {
protected readonly submitted = this.submittedState.asReadonly();
protected readonly isSubmitting = this.isSubmittingState.asReadonly();
protected readonly serverError = this.serverErrorState.asReadonly();
+ protected readonly passwordVisible = this.passwordVisibleState.asReadonly();
+
+ protected setPasswordVisibility(visible: boolean): void {
+ this.passwordVisibleState.set(visible);
+ }
protected updatePassword(controlName: PasswordControlName, value: string | number): void {
this.form.controls[controlName].setValue(String(value));