Skip to content

Commit 700f82b

Browse files
committed
consolidate verification flow state into currentVerifyFlow
- Removed verifyingEmail, verifyingPhone, and formTitle properties - Refactored component logic and template to use currentVerifyFlow exclusively - Updated unit tests to align with new flow-based state model - Improved maintainability and reduced risk of inconsistent state
1 parent c5b64d1 commit 700f82b

File tree

3 files changed

+46
-117
lines changed

3 files changed

+46
-117
lines changed

src/app/auth/components/verify/verify.component.html

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<ng-container
22
*ngIf="
3-
(verifyingPhone || showCaptchaForEmail) && captchaEnabled && !captchaPassed;
3+
(currentVerifyFlow === 'phone' || showCaptchaForEmail) &&
4+
captchaEnabled &&
5+
!captchaPassed;
46
else verifyFormElement
57
"
68
>
@@ -19,25 +21,27 @@
1921
<ng-template #verifyFormElement>
2022
<form [formGroup]="verifyForm" (ngSubmit)="onSubmit(verifyForm.value)">
2123
<h1 class="page-title">
22-
{{ formTitle }}
24+
{{
25+
currentVerifyFlow === 'email' ? 'Verify Email' : 'Verify Phone Number'
26+
}}
2327
</h1>
2428
<p class="verify-text">
2529
A verification code has been sent to your
26-
{{ verifyingEmail ? 'email address' : 'mobile device' }}.
27-
<span *ngIf="!verifyingEmail"
28-
>Permanent only supports US and Canada numbers.</span
29-
>
30+
{{ currentVerifyFlow === 'email' ? 'email address' : 'mobile device' }}.
31+
<span *ngIf="currentVerifyFlow === 'phone'">
32+
Permanent only supports US and Canada numbers.
33+
</span>
3034
</p>
3135
<p class="verify-text">Enter it below to continue.</p>
3236
<div class="input-container">
3337
<pr-form-input-glam
34-
type="{{ verifyingEmail ? 'email' : 'tel' }}"
38+
type="{{ currentVerifyFlow === 'email' ? 'email' : 'tel' }}"
3539
fieldName="token"
3640
[variant]="'dark'"
3741
placeholder="Code"
3842
[control]="verifyForm.controls['token']"
3943
[config]="{
40-
autocomplete: verifyingEmail ? 'email' : 'tel',
44+
autocomplete: currentVerifyFlow === 'email' ? 'email' : 'tel',
4145
autocorrect: 'off',
4246
autocapitalize: 'off',
4347
spellcheck: 'off'

src/app/auth/components/verify/verify.component.spec.ts

+8-77
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ describe('VerifyComponent', () => {
3232
const config: TestModuleMetadata = cloneDeep(Testing.BASE_TEST_CONFIG);
3333

3434
config.declarations.push(VerifyComponent);
35-
3635
config.imports.push(SharedModule);
37-
3836
config.providers.push(HttpService);
3937
config.providers.push(ApiService);
4038
config.providers.push(AccountService);
@@ -57,18 +55,14 @@ describe('VerifyComponent', () => {
5755
});
5856

5957
config.providers.push(EventService);
60-
61-
// Define the re-captcha element as a custom element so it's only mocked out
6258
config.schemas = [CUSTOM_ELEMENTS_SCHEMA];
6359

6460
await TestBed.configureTestingModule(config).compileComponents();
6561

6662
httpMock = TestBed.get(HttpTestingController);
67-
6863
accountService = TestBed.get(AccountService);
6964

7065
const authResponse = new AuthResponse(authResponseData);
71-
7266
accountService.setAccount(authResponse.getAccountVO());
7367
accountService.setArchive(authResponse.getArchiveVO());
7468

@@ -79,7 +73,6 @@ describe('VerifyComponent', () => {
7973

8074
afterEach(() => {
8175
accountService.clear();
82-
// httpMock.verify();
8376
});
8477

8578
it('should create', async () => {
@@ -88,80 +81,46 @@ describe('VerifyComponent', () => {
8881
expect(component).toBeTruthy();
8982
});
9083

91-
// it('should send email verification if sendEmail flag set', async () => {
92-
// await init(defaultAuthData, {sendEmail: true});
93-
// const req = httpMock.expectOne(`${environment.apiUrl}/auth/resendMailCreatedAccount`);
94-
// });
95-
96-
// it('should send sms verification if sendSms flag set', async () => {
97-
// await init(defaultAuthData, {sendSms: true});
98-
// const req = httpMock.expectOne(`${environment.apiUrl}/auth/resendTextCreatedAccount`);
99-
// });
100-
10184
it('should require only email verification if only email unverified', async () => {
10285
await init(defaultAuthData, { sendEmail: true });
10386

104-
expect(component.verifyingEmail).toBeTruthy();
105-
expect(component.needsEmail).toBeTruthy();
106-
expect(component.needsPhone).toBeFalsy();
107-
108-
const account = accountService.getAccount();
109-
110-
expect(account.emailNeedsVerification()).toBeTrue();
111-
expect(account.phoneNeedsVerification()).toBeFalse();
87+
expect(component.currentVerifyFlow).toBe('email');
88+
expect(component.needsEmail).toBeTrue();
89+
expect(component.needsPhone).toBeFalse();
11290
});
11391

11492
it('should require only phone verification if only phone unverified', async () => {
11593
const unverifiedPhoneData = require('@root/test/responses/auth.verify.unverifiedPhone.success.json');
11694
await init(unverifiedPhoneData, { sendSms: true });
11795

118-
expect(component.verifyingPhone).toBeTruthy();
119-
expect(component.needsPhone).toBeTruthy();
120-
expect(component.needsEmail).toBeFalsy();
96+
expect(component.currentVerifyFlow).toBe('phone');
97+
expect(component.needsPhone).toBeTrue();
98+
expect(component.needsEmail).toBeFalse();
12199
});
122100

123101
it('should require verification of both if both unverified, and verify email first', async () => {
124102
const unverifiedBothData = require('@root/test/responses/auth.verify.unverifiedBoth.success.json');
125103
await init(unverifiedBothData);
126104

127-
expect(component.verifyingEmail).toBeTrue();
128-
expect(component.verifyingPhone).toBeFalse();
129-
105+
expect(component.currentVerifyFlow).toBe('email');
130106
expect(component.needsEmail).toBeTrue();
131107
expect(component.needsPhone).toBeTrue();
132-
133-
const account = accountService.getAccount();
134-
135-
expect(account.emailNeedsVerification()).toBeTrue();
136-
expect(account.phoneNeedsVerification()).toBeTrue();
137108
});
138109

139110
it('should verify email and then switch to phone verification if needed', async () => {
140111
const unverifiedBothData = require('@root/test/responses/auth.verify.unverifiedBoth.success.json');
141-
142-
// Remove query params -- let accountService drive both verifications
143112
await init(unverifiedBothData);
144113

145-
expect(component.verifyingEmail).toBeTrue();
146-
expect(component.needsPhone).toBeTrue();
147-
expect(component.needsEmail).toBeTrue();
148-
149114
const account = accountService.getAccount();
150115

151116
expect(account.emailNeedsVerification()).toBeTrue();
152117
expect(account.phoneNeedsVerification()).toBeTrue();
153118

154119
component.onSubmit(component.verifyForm.value).then(() => {
155120
expect(component.waiting).toBeFalse();
156-
expect(component.verifyingEmail).toBeFalse();
121+
expect(component.currentVerifyFlow).toBe('phone');
157122
expect(component.needsEmail).toBeFalse();
158123
expect(component.needsPhone).toBeTrue();
159-
expect(component.verifyingPhone).toBeTrue();
160-
161-
const updatedAccount = accountService.getAccount();
162-
163-
expect(updatedAccount.emailNeedsVerification()).toBeFalse();
164-
expect(updatedAccount.phoneNeedsVerification()).toBeTrue();
165124
});
166125

167126
expect(component.waiting).toBeTrue();
@@ -176,11 +135,6 @@ describe('VerifyComponent', () => {
176135
await init(unverifiedEmailData, { sendEmail: true });
177136

178137
const finishSpy = spyOn(component, 'finish');
179-
180-
expect(component.verifyingEmail).toBeTruthy();
181-
expect(component.needsPhone).toBeFalsy();
182-
expect(component.needsEmail).toBeTruthy();
183-
184138
component.onSubmit(component.verifyForm.value).then(() => {
185139
expect(component.waiting).toBeFalsy();
186140
expect(component.needsEmail).toBeFalsy();
@@ -200,12 +154,6 @@ describe('VerifyComponent', () => {
200154
await init(unverifiedPhoneData, { sendSms: true });
201155

202156
const finishSpy = spyOn(component, 'finish');
203-
204-
expect(component.verifyingPhone).toBeTruthy();
205-
expect(component.verifyingEmail).toBeFalsy();
206-
expect(component.needsPhone).toBeTruthy();
207-
expect(component.needsEmail).toBeFalsy();
208-
209157
component.onSubmit(component.verifyForm.value).then(() => {
210158
expect(component.waiting).toBeFalsy();
211159
expect(component.needsEmail).toBeFalsy();
@@ -224,8 +172,6 @@ describe('VerifyComponent', () => {
224172
const unverifiedPhoneData = require('@root/test/responses/auth.verify.unverifiedPhone.success.json');
225173
await init(unverifiedPhoneData, { sendSms: true });
226174

227-
// Testing environments might not have the site key enabled,
228-
// so force captchaEnabled to be true.
229175
component.captchaEnabled = true;
230176

231177
expect(component.captchaPassed).toBeFalsy();
@@ -236,19 +182,4 @@ describe('VerifyComponent', () => {
236182
expect(component.captchaPassed).toBeTruthy();
237183
expect(component.canSendCodes('phone')).toBeTruthy();
238184
});
239-
240-
it('should set flow to email when only email is unverified', async () => {
241-
await init(defaultAuthData, { sendEmail: true });
242-
243-
expect(component.currentVerifyFlow).toBe('email');
244-
expect(component.formTitle).toBe('Verify Email');
245-
});
246-
247-
it('should set flow to phone when only phone is unverified', async () => {
248-
const unverifiedPhoneData = require('@root/test/responses/auth.verify.unverifiedPhone.success.json');
249-
await init(unverifiedPhoneData, { sendSms: true });
250-
251-
expect(component.currentVerifyFlow).toBe('phone');
252-
expect(component.formTitle).toBe('Verify Phone Number');
253-
});
254185
});

src/app/auth/components/verify/verify.component.ts

+26-32
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@ import { C } from '@angular/cdk/keycodes';
2424
export class VerifyComponent implements OnInit {
2525
@HostBinding('class.pr-auth-form') classBinding = true;
2626
verifyForm: UntypedFormGroup;
27-
formTitle = 'Verify Email';
2827
waiting: boolean;
2928

30-
verifyingEmail = true;
31-
verifyingPhone = false;
32-
3329
currentVerifyFlow: 'none' | 'email' | 'phone' = 'none';
3430

3531
needsEmail: boolean;
@@ -110,15 +106,8 @@ export class VerifyComponent implements OnInit {
110106
}
111107
}
112108

113-
switch (this.currentVerifyFlow) {
114-
case 'phone':
115-
this.verifyingEmail = false;
116-
this.verifyingPhone = true;
117-
this.formTitle = 'Verify Phone Number';
118-
break;
119-
case 'none':
120-
this.router.navigate(['/private'], { queryParamsHandling: 'preserve' });
121-
break;
109+
if (this.currentVerifyFlow === 'none') {
110+
this.router.navigate(['/private'], { queryParamsHandling: 'preserve' });
122111
}
123112
}
124113

@@ -135,12 +124,15 @@ export class VerifyComponent implements OnInit {
135124

136125
let verifyPromise: Promise<AuthResponse>;
137126

138-
if (this.verifyingEmail) {
139-
verifyPromise = this.accountService.verifyEmail(formValue.token);
140-
} else if (this.verifyingPhone) {
141-
verifyPromise = this.accountService.verifyPhone(formValue.token);
142-
} else {
143-
return;
127+
switch (this.currentVerifyFlow) {
128+
case 'email':
129+
verifyPromise = this.accountService.verifyEmail(formValue.token);
130+
break;
131+
case 'phone':
132+
verifyPromise = this.accountService.verifyPhone(formValue.token);
133+
break;
134+
default:
135+
return;
144136
}
145137

146138
return verifyPromise
@@ -163,9 +155,7 @@ export class VerifyComponent implements OnInit {
163155

164156
if (this.needsPhone) {
165157
this.verifyForm.controls['token'].setValue('');
166-
this.verifyingEmail = false;
167-
this.verifyingPhone = true;
168-
this.formTitle = 'Verify Phone Number';
158+
this.currentVerifyFlow = 'phone';
169159
} else {
170160
this.finish();
171161
}
@@ -183,14 +173,19 @@ export class VerifyComponent implements OnInit {
183173
this.waiting = true;
184174

185175
let resendPromise: Promise<AuthResponse>;
186-
if (this.verifyingEmail) {
187-
if (this.canSendCodes('email')) {
188-
resendPromise = this.accountService.resendEmailVerification();
189-
}
190-
} else {
191-
if (this.canSendCodes('phone')) {
192-
resendPromise = this.accountService.resendPhoneVerification();
193-
}
176+
switch (this.currentVerifyFlow) {
177+
case 'email':
178+
if (this.canSendCodes('email')) {
179+
resendPromise = this.accountService.resendEmailVerification();
180+
}
181+
break;
182+
case 'phone':
183+
if (this.canSendCodes('phone')) {
184+
resendPromise = this.accountService.resendPhoneVerification();
185+
}
186+
break;
187+
default:
188+
return;
194189
}
195190

196191
resendPromise
@@ -219,9 +214,8 @@ export class VerifyComponent implements OnInit {
219214
.then((response: ArchiveResponse) => {
220215
this.message.showMessage({
221216
message: `${
222-
this.verifyingEmail ? 'Email' : 'Phone number'
217+
this.currentVerifyFlow === 'email' ? 'Email' : 'Phone number'
223218
} verified.`,
224-
style: 'success',
225219
});
226220
if (this.route.snapshot.queryParams.shareByUrl) {
227221
this.router

0 commit comments

Comments
 (0)