Skip to content

Commit fe98feb

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 fe98feb

File tree

3 files changed

+45
-119
lines changed

3 files changed

+45
-119
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-79
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,89 +73,52 @@ describe('VerifyComponent', () => {
7973

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

8578
it('should create', async () => {
8679
await init();
87-
8880
expect(component).toBeTruthy();
8981
});
9082

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-
10183
it('should require only email verification if only email unverified', async () => {
10284
await init(defaultAuthData, { sendEmail: true });
10385

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();
86+
expect(component.currentVerifyFlow).toBe('email');
87+
expect(component.needsEmail).toBeTrue();
88+
expect(component.needsPhone).toBeFalse();
11289
});
11390

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

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

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

127-
expect(component.verifyingEmail).toBeTrue();
128-
expect(component.verifyingPhone).toBeFalse();
129-
104+
expect(component.currentVerifyFlow).toBe('email');
130105
expect(component.needsEmail).toBeTrue();
131106
expect(component.needsPhone).toBeTrue();
132-
133-
const account = accountService.getAccount();
134-
135-
expect(account.emailNeedsVerification()).toBeTrue();
136-
expect(account.phoneNeedsVerification()).toBeTrue();
137107
});
138108

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

145-
expect(component.verifyingEmail).toBeTrue();
146-
expect(component.needsPhone).toBeTrue();
147-
expect(component.needsEmail).toBeTrue();
148-
149113
const account = accountService.getAccount();
150-
151114
expect(account.emailNeedsVerification()).toBeTrue();
152115
expect(account.phoneNeedsVerification()).toBeTrue();
153116

154117
component.onSubmit(component.verifyForm.value).then(() => {
155118
expect(component.waiting).toBeFalse();
156-
expect(component.verifyingEmail).toBeFalse();
119+
expect(component.currentVerifyFlow).toBe('phone');
157120
expect(component.needsEmail).toBeFalse();
158121
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();
165122
});
166123

167124
expect(component.waiting).toBeTrue();
@@ -176,11 +133,6 @@ describe('VerifyComponent', () => {
176133
await init(unverifiedEmailData, { sendEmail: true });
177134

178135
const finishSpy = spyOn(component, 'finish');
179-
180-
expect(component.verifyingEmail).toBeTruthy();
181-
expect(component.needsPhone).toBeFalsy();
182-
expect(component.needsEmail).toBeTruthy();
183-
184136
component.onSubmit(component.verifyForm.value).then(() => {
185137
expect(component.waiting).toBeFalsy();
186138
expect(component.needsEmail).toBeFalsy();
@@ -200,12 +152,6 @@ describe('VerifyComponent', () => {
200152
await init(unverifiedPhoneData, { sendSms: true });
201153

202154
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-
209155
component.onSubmit(component.verifyForm.value).then(() => {
210156
expect(component.waiting).toBeFalsy();
211157
expect(component.needsEmail).toBeFalsy();
@@ -224,8 +170,6 @@ describe('VerifyComponent', () => {
224170
const unverifiedPhoneData = require('@root/test/responses/auth.verify.unverifiedPhone.success.json');
225171
await init(unverifiedPhoneData, { sendSms: true });
226172

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

231175
expect(component.captchaPassed).toBeFalsy();
@@ -236,19 +180,4 @@ describe('VerifyComponent', () => {
236180
expect(component.captchaPassed).toBeTruthy();
237181
expect(component.canSendCodes('phone')).toBeTruthy();
238182
});
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-
});
254183
});

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

+25-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,6 @@ 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';
169158
} else {
170159
this.finish();
171160
}
@@ -183,14 +172,19 @@ export class VerifyComponent implements OnInit {
183172
this.waiting = true;
184173

185174
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-
}
175+
switch (this.currentVerifyFlow) {
176+
case 'email':
177+
if (this.canSendCodes('email')) {
178+
resendPromise = this.accountService.resendEmailVerification();
179+
}
180+
break;
181+
case 'phone':
182+
if (this.canSendCodes('phone')) {
183+
resendPromise = this.accountService.resendPhoneVerification();
184+
}
185+
break;
186+
default:
187+
return;
194188
}
195189

196190
resendPromise
@@ -219,9 +213,8 @@ export class VerifyComponent implements OnInit {
219213
.then((response: ArchiveResponse) => {
220214
this.message.showMessage({
221215
message: `${
222-
this.verifyingEmail ? 'Email' : 'Phone number'
216+
this.currentVerifyFlow === 'email' ? 'Email' : 'Phone number'
223217
} verified.`,
224-
style: 'success',
225218
});
226219
if (this.route.snapshot.queryParams.shareByUrl) {
227220
this.router

0 commit comments

Comments
 (0)