Align landlord profile validation (#47)

This commit is contained in:
nessar committed 2026-08-17 14:18:16 +02:00
1 parent d1cdc6eaeb
commit 66fa95dabd
13 files changed
+462 -32

No files matched your search

@@ -69,6 +69,8 @@
[profile]="profileModel()"
[saving]="saving()"
[saveError]="saveError()"
[saveFieldErrors]="saveFieldErrors()"
(fieldChanged)="clearSaveFieldError($event)"
(saveRequested)="save($event)"
/>
}
@@ -97,4 +97,43 @@ describe('SettingsPage', () => {
'alex@example.com',
);
});
it('keeps structured profile errors beside their field until that field changes', async () => {
profile.updateProfile.mockReturnValue(
throwError(
() =>
new HttpErrorResponse({
error: {
code: 'validation_failed',
errors: [{ field: 'phoneValid', code: 'assert_true' }],
},
status: 400,
}),
),
);
const fixture = TestBed.createComponent(SettingsPage);
fixture.detectChanges();
await fixture.whenStable();
fixture.nativeElement.querySelector('button.primary-action').click();
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.textContent).toContain(
'Saisissez un numéro de téléphone valide.',
);
expect(fixture.nativeElement.textContent).not.toContain(
'Veuillez corriger les champs signalés.',
);
const phone = fixture.nativeElement.querySelector(
'input#profile-phone',
) as HTMLInputElement;
phone.value = '+33612345678';
phone.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(fixture.nativeElement.textContent).not.toContain(
'Saisissez un numéro de téléphone valide.',
);
});
});
@@ -6,7 +6,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatRadioModule } from '@angular/material/radio';
import { LandlordProfileForm } from '../landlord-profile-form/landlord-profile-form';
import { httpErrorMessage } from '../../services/http-error-message';
import { FieldValidationError, saveFailure } from '../../services/http-error-message';
import { LandlordProfile, LandlordProfileService } from '../../services/landlord-profile.service';
import { SessionService } from '../../services/session.service';
import { ThemeService } from '../../services/theme.service';
@@ -45,6 +45,7 @@ export class SettingsPage {
readonly profileError = signal('');
readonly saveError = signal('');
readonly saveFieldErrors = signal<FieldValidationError[]>([]);
readonly saveSuccess = signal('');
constructor() {
@@ -79,6 +80,7 @@ export class SettingsPage {
if (this.saving()) return;
this.saveSuccess.set('');
this.saveError.set('');
this.saveFieldErrors.set([]);
this.saving.set(true);
this.landlordProfile
.updateProfile(profile)
@@ -90,14 +92,21 @@ export class SettingsPage {
this.saving.set(false);
},
error: (error: unknown) => {
this.saveError.set(
httpErrorMessage(
error,
'Impossible d’enregistrer votre profil bailleur. Réessayez.',
),
const failure = saveFailure(
error,
'Impossible d’enregistrer votre profil bailleur. Réessayez.',
);
this.saveError.set(failure.message);
this.saveFieldErrors.set(failure.fieldErrors);
this.saving.set(false);
},
});
}
clearSaveFieldError(field: string): void {
const remaining = this.saveFieldErrors().filter((error) => error.field !== field);
if (remaining.length === this.saveFieldErrors().length) return;
this.saveFieldErrors.set(remaining);
if (!remaining.length) this.saveError.set('');
}
}