Skip to content

Commit 8b5c162

Browse files
bstolinskidt-iohk
andauthored
fix(cat-voices): update email validation logic for agree to receive emails checkbox (#3488)
* fix: update email validation logic and add tests for new conditions * fix: correct username spelling --------- Signed-off-by: Bartek Stoliński <[email protected]> Co-authored-by: Dominik Toton <[email protected]>
1 parent e4389b0 commit 8b5c162

File tree

4 files changed

+207
-1
lines changed

4 files changed

+207
-1
lines changed

catalyst_voices/packages/internal/catalyst_voices_blocs/lib/src/registration/cubits/base_profile_cubit.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ final class BaseProfileCubit extends Cubit<BaseProfileStateData>
4545
@override
4646
void updateEmail(Email value) {
4747
final receiveEmails = state.receiveEmails.copyWith(
48-
isAccepted: value.isNotValid ? false : null,
48+
isAccepted: value.isEmptyOrNotValid ? false : null,
4949
isEnabled: value.isNonEmptyAndValid,
5050
);
5151

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import 'package:bloc_test/bloc_test.dart';
2+
import 'package:catalyst_voices_blocs/src/catalyst_voices_blocs.dart';
3+
import 'package:catalyst_voices_blocs/src/registration/cubits/base_profile_cubit.dart';
4+
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
5+
import 'package:flutter_test/flutter_test.dart';
6+
7+
void main() {
8+
group(BaseProfileCubit, () {
9+
late BaseProfileCubit baseProfileCubit;
10+
11+
setUp(() {
12+
baseProfileCubit = BaseProfileCubit();
13+
});
14+
15+
tearDown(() async {
16+
await baseProfileCubit.close();
17+
});
18+
19+
test('creates recovery progress with current username and email', () {
20+
baseProfileCubit
21+
..updateUsername(const Username.dirty('testUser'))
22+
..updateEmail(const Email.dirty('[email protected]'));
23+
24+
final progress = baseProfileCubit.createRecoverProgress();
25+
26+
expect(progress.username, 'testUser');
27+
expect(progress.email, '[email protected]');
28+
});
29+
30+
blocTest<BaseProfileCubit, BaseProfileStateData>(
31+
'emits updated conditionsAccepted when updateConditions is called with true',
32+
build: () => baseProfileCubit,
33+
act: (cubit) => cubit.updateConditions(accepted: true),
34+
expect: () => [
35+
isA<BaseProfileStateData>().having((e) => e.conditionsAccepted, 'conditionsAccepted', true),
36+
],
37+
);
38+
39+
blocTest<BaseProfileCubit, BaseProfileStateData>(
40+
'emits updated conditionsAccepted when updateConditions is called with false',
41+
build: () => baseProfileCubit,
42+
act: (cubit) => cubit.updateConditions(accepted: false),
43+
expect: () => [
44+
isA<BaseProfileStateData>().having(
45+
(e) => e.conditionsAccepted,
46+
'conditionsAccepted',
47+
false,
48+
),
49+
],
50+
);
51+
52+
blocTest<BaseProfileCubit, BaseProfileStateData>(
53+
'emits updated drepApprovalContingencyAccepted when updateDrepApprovalContingency is called with true',
54+
build: () => baseProfileCubit,
55+
act: (cubit) => cubit.updateDrepApprovalContingency(accepted: true),
56+
expect: () => [
57+
isA<BaseProfileStateData>().having(
58+
(e) => e.drepApprovalContingencyAccepted,
59+
'drepApprovalContingencyAccepted',
60+
true,
61+
),
62+
],
63+
);
64+
65+
blocTest<BaseProfileCubit, BaseProfileStateData>(
66+
'emits updated drepApprovalContingencyAccepted when updateDrepApprovalContingency is called with false',
67+
build: () => baseProfileCubit,
68+
act: (cubit) => cubit.updateDrepApprovalContingency(accepted: false),
69+
expect: () => [
70+
isA<BaseProfileStateData>().having(
71+
(e) => e.drepApprovalContingencyAccepted,
72+
'drepApprovalContingencyAccepted',
73+
false,
74+
),
75+
],
76+
);
77+
78+
blocTest<BaseProfileCubit, BaseProfileStateData>(
79+
'emits updated email when updateEmail is called with valid email',
80+
build: () => baseProfileCubit,
81+
act: (cubit) => cubit.updateEmail(const Email.dirty('[email protected]')),
82+
expect: () => [
83+
isA<BaseProfileStateData>()
84+
.having((e) => e.email.value, 'email', '[email protected]')
85+
.having((e) => e.receiveEmails.isEnabled, 'receiveEmails.isEnabled', true),
86+
],
87+
);
88+
89+
blocTest<BaseProfileCubit, BaseProfileStateData>(
90+
'emits updated email with disabled receiveEmails when updateEmail is called with invalid email',
91+
build: () => baseProfileCubit,
92+
act: (cubit) => cubit.updateEmail(const Email.dirty('invalid')),
93+
expect: () => [
94+
isA<BaseProfileStateData>()
95+
.having((e) => e.email.value, 'email', 'invalid')
96+
.having((e) => e.receiveEmails.isEnabled, 'receiveEmails.isEnabled', false)
97+
.having((e) => e.receiveEmails.isAccepted, 'receiveEmails.isAccepted', false),
98+
],
99+
);
100+
101+
blocTest<BaseProfileCubit, BaseProfileStateData>(
102+
'emits updated email with disabled receiveEmails when updateEmail is called with empty email',
103+
build: () => baseProfileCubit,
104+
act: (cubit) => cubit.updateEmail(const Email.dirty()),
105+
expect: () => [
106+
isA<BaseProfileStateData>()
107+
.having((e) => e.email.value, 'email', '')
108+
.having((e) => e.receiveEmails.isEnabled, 'receiveEmails.isEnabled', false)
109+
.having((e) => e.receiveEmails.isAccepted, 'receiveEmails.isAccepted', false),
110+
],
111+
);
112+
113+
blocTest<BaseProfileCubit, BaseProfileStateData>(
114+
'emits updated receiveEmails when updateReceiveEmails is called with true',
115+
build: () => baseProfileCubit,
116+
act: (cubit) => cubit.updateReceiveEmails(isAccepted: true),
117+
expect: () => [
118+
isA<BaseProfileStateData>().having(
119+
(e) => e.receiveEmails.isAccepted,
120+
'receiveEmails.isAccepted',
121+
true,
122+
),
123+
],
124+
);
125+
126+
blocTest<BaseProfileCubit, BaseProfileStateData>(
127+
'emits updated receiveEmails when updateReceiveEmails is called with false',
128+
build: () => baseProfileCubit,
129+
act: (cubit) => cubit.updateReceiveEmails(isAccepted: false),
130+
expect: () => [
131+
isA<BaseProfileStateData>().having(
132+
(e) => e.receiveEmails.isAccepted,
133+
'receiveEmails.isAccepted',
134+
false,
135+
),
136+
],
137+
);
138+
139+
blocTest<BaseProfileCubit, BaseProfileStateData>(
140+
'emits updated tosAndPrivacyPolicyAccepted when updateTosAndPrivacyPolicy is called with true',
141+
build: () => baseProfileCubit,
142+
act: (cubit) => cubit.updateTosAndPrivacyPolicy(accepted: true),
143+
expect: () => [
144+
isA<BaseProfileStateData>().having(
145+
(e) => e.tosAndPrivacyPolicyAccepted,
146+
'tosAndPrivacyPolicyAccepted',
147+
true,
148+
),
149+
],
150+
);
151+
152+
blocTest<BaseProfileCubit, BaseProfileStateData>(
153+
'emits updated tosAndPrivacyPolicyAccepted when updateTosAndPrivacyPolicy is called with false',
154+
build: () => baseProfileCubit,
155+
act: (cubit) => cubit.updateTosAndPrivacyPolicy(accepted: false),
156+
expect: () => [
157+
isA<BaseProfileStateData>().having(
158+
(e) => e.tosAndPrivacyPolicyAccepted,
159+
'tosAndPrivacyPolicyAccepted',
160+
false,
161+
),
162+
],
163+
);
164+
165+
blocTest<BaseProfileCubit, BaseProfileStateData>(
166+
'emits updated username when updateUsername is called',
167+
build: () => baseProfileCubit,
168+
act: (cubit) => cubit.updateUsername(const Username.dirty('testUser')),
169+
expect: () => [
170+
isA<BaseProfileStateData>().having((e) => e.username.value, 'username', 'testUser'),
171+
],
172+
);
173+
});
174+
}

catalyst_voices/packages/internal/catalyst_voices_view_models/lib/src/authentication/email.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ final class Email extends FormzInput<String, EmailValidationException> {
1515

1616
bool get isNonEmptyAndValid => value.isNotEmpty && isValid;
1717

18+
bool get isEmptyOrNotValid => value.isEmpty || isNotValid;
19+
1820
@override
1921
EmailValidationException? validator(String value) {
2022
if (!lengthRange.contains(value.length)) {

catalyst_voices/packages/internal/catalyst_voices_view_models/test/authentication/email_test.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,36 @@ void main() {
3939

4040
expect(error, isA<EmailPatternInvalidException>());
4141
});
42+
43+
test('isEmptyOrNotValid returns true for empty email', () {
44+
// When
45+
const email = Email.pure();
46+
47+
// Then
48+
expect(email.isEmptyOrNotValid, isTrue);
49+
});
50+
51+
test('isEmptyOrNotValid returns true for invalid email', () {
52+
// Given
53+
const value = 'invalid@email';
54+
55+
// When
56+
const email = Email.pure(value);
57+
58+
// Then
59+
expect(email.isEmptyOrNotValid, isTrue);
60+
});
61+
62+
test('isEmptyOrNotValid returns false for valid email', () {
63+
// Given
64+
const value = '[email protected]';
65+
66+
// When
67+
const email = Email.pure(value);
68+
69+
// Then
70+
expect(email.isEmptyOrNotValid, isFalse);
71+
});
4272
});
4373
});
4474
}

0 commit comments

Comments
 (0)