Skip to content

Commit d6ba38a

Browse files
committed
test: add service selection validation and mock BudgetStateService
1 parent 0e6933e commit d6ba38a

File tree

3 files changed

+185
-51
lines changed

3 files changed

+185
-51
lines changed

src/app/budget-application-form/budget-application-form.component.spec.ts

Lines changed: 166 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { BudgetApplicationFormComponent } from './budget-application-form.component';
4+
import { signal, WritableSignal } from '@angular/core';
5+
import { BudgetStateService } from '../../services/budgetStatusService';
6+
import type { Service } from '../../config/servicesConfig';
47

58
describe('BudgetApplicationFormComponent', () => {
69
let component: BudgetApplicationFormComponent;
710
let fixture: ComponentFixture<BudgetApplicationFormComponent>;
11+
let mockBudgetStateService: {
12+
services: WritableSignal<Service[]>;
13+
total: WritableSignal<number>;
14+
};
815

916
beforeEach(async () => {
17+
mockBudgetStateService = {
18+
services: signal<Service[]>([]),
19+
total: signal(0),
20+
};
21+
1022
await TestBed.configureTestingModule({
1123
imports: [BudgetApplicationFormComponent],
24+
providers: [
25+
{ provide: BudgetStateService, useValue: mockBudgetStateService },
26+
],
1227
}).compileComponents();
1328

1429
fixture = TestBed.createComponent(BudgetApplicationFormComponent);
@@ -20,7 +35,35 @@ describe('BudgetApplicationFormComponent', () => {
2035
expect(component).toBeTruthy();
2136
});
2237

38+
it('should display an error message when there are no services selected', () => {
39+
mockBudgetStateService.services.set([
40+
{ title: 'SEO', description: 'SEO service', price: 300, selected: false },
41+
{ title: 'Ads', description: 'Ads service', price: 400, selected: false },
42+
]);
43+
mockBudgetStateService.total.set(0);
44+
component.formData.name = 'John Doe';
45+
component.formData.email = 'john.doe@gmail.com';
46+
component.formData.phone = '123456789';
47+
component.onSubmit();
48+
49+
fixture.detectChanges();
50+
const errorMessage = fixture.nativeElement.querySelector('.error-message');
51+
expect(errorMessage).toBeTruthy();
52+
expect(errorMessage.textContent).toBe(
53+
'You need to select at least one service to create a budget'
54+
);
55+
});
56+
2357
it('should display an error message when name is empty', () => {
58+
mockBudgetStateService.services.set([
59+
{
60+
title: 'SEO',
61+
description: 'SEO service',
62+
price: 300,
63+
selected: true,
64+
},
65+
]);
66+
mockBudgetStateService.total.set(300);
2467
component.formData.name = '';
2568
component.onSubmit();
2669

@@ -31,6 +74,15 @@ describe('BudgetApplicationFormComponent', () => {
3174
});
3275

3376
it('should display an error message when name is not a string', () => {
77+
mockBudgetStateService.services.set([
78+
{
79+
title: 'SEO',
80+
description: 'SEO service',
81+
price: 300,
82+
selected: true,
83+
},
84+
]);
85+
mockBudgetStateService.total.set(300);
3486
// @ts-ignore
3587
component.formData.name = 123;
3688
component.onSubmit();
@@ -42,6 +94,15 @@ describe('BudgetApplicationFormComponent', () => {
4294
});
4395

4496
it('should display an error message when name is not enough characters', () => {
97+
mockBudgetStateService.services.set([
98+
{
99+
title: 'SEO',
100+
description: 'SEO service',
101+
price: 300,
102+
selected: true,
103+
},
104+
]);
105+
mockBudgetStateService.total.set(300);
45106
component.formData.name = 'b';
46107
component.onSubmit();
47108

@@ -54,6 +115,15 @@ describe('BudgetApplicationFormComponent', () => {
54115
});
55116

56117
it('should display an error message when name is not letters only', () => {
118+
mockBudgetStateService.services.set([
119+
{
120+
title: 'SEO',
121+
description: 'SEO service',
122+
price: 300,
123+
selected: true,
124+
},
125+
]);
126+
mockBudgetStateService.total.set(300);
57127
component.formData.name = '123';
58128
component.onSubmit();
59129

@@ -64,6 +134,15 @@ describe('BudgetApplicationFormComponent', () => {
64134
});
65135

66136
it('should display an error message when email is empty', () => {
137+
mockBudgetStateService.services.set([
138+
{
139+
title: 'SEO',
140+
description: 'SEO service',
141+
price: 300,
142+
selected: true,
143+
},
144+
]);
145+
mockBudgetStateService.total.set(300);
67146
component.formData.name = 'John Doe';
68147
component.formData.email = '';
69148
component.onSubmit();
@@ -75,6 +154,15 @@ describe('BudgetApplicationFormComponent', () => {
75154
});
76155

77156
it('should display an error message when email is not a string', () => {
157+
mockBudgetStateService.services.set([
158+
{
159+
title: 'SEO',
160+
description: 'SEO service',
161+
price: 300,
162+
selected: true,
163+
},
164+
]);
165+
mockBudgetStateService.total.set(300);
78166
// @ts-ignore
79167
component.formData.email = 123;
80168
component.formData.name = 'John Doe';
@@ -87,6 +175,15 @@ describe('BudgetApplicationFormComponent', () => {
87175
});
88176

89177
it('should display an error message when email does not contain an @', () => {
178+
mockBudgetStateService.services.set([
179+
{
180+
title: 'SEO',
181+
description: 'SEO service',
182+
price: 300,
183+
selected: true,
184+
},
185+
]);
186+
mockBudgetStateService.total.set(300);
90187
component.formData.name = 'John Doe';
91188
component.formData.email = '123';
92189
component.onSubmit();
@@ -98,28 +195,59 @@ describe('BudgetApplicationFormComponent', () => {
98195
});
99196

100197
it('should display an error message when email does not contain a dot after @', () => {
198+
mockBudgetStateService.services.set([
199+
{
200+
title: 'SEO',
201+
description: 'SEO service',
202+
price: 300,
203+
selected: true,
204+
},
205+
]);
206+
mockBudgetStateService.total.set(300);
101207
component.formData.name = 'John Doe';
102208
component.formData.email = '123@';
103209
component.onSubmit();
104210

105211
fixture.detectChanges();
106212
const errorMessage = fixture.nativeElement.querySelector('.error-message');
107213
expect(errorMessage).toBeTruthy();
108-
expect(errorMessage.textContent).toBe('Email must contain .');
214+
expect(errorMessage.textContent).toBe(
215+
'Email must contain a dot after an @'
216+
);
109217
});
110218

111219
it('should display an error message when email does contain a dot before @ and not after', () => {
220+
mockBudgetStateService.services.set([
221+
{
222+
title: 'SEO',
223+
description: 'SEO service',
224+
price: 300,
225+
selected: true,
226+
},
227+
]);
228+
mockBudgetStateService.total.set(300);
112229
component.formData.name = 'John Doe';
113230
component.formData.email = 'john.doe@';
114231
component.onSubmit();
115232

116233
fixture.detectChanges();
117234
const errorMessage = fixture.nativeElement.querySelector('.error-message');
118235
expect(errorMessage).toBeTruthy();
119-
expect(errorMessage.textContent).toBe('Email must contain .');
236+
expect(errorMessage.textContent).toBe(
237+
'Email must contain a dot after an @'
238+
);
120239
});
121240

122241
it('should display an error message when phone is empty', () => {
242+
mockBudgetStateService.services.set([
243+
{
244+
title: 'SEO',
245+
description: 'SEO service',
246+
price: 300,
247+
selected: true,
248+
},
249+
]);
250+
mockBudgetStateService.total.set(300);
123251
component.formData.name = 'John Doe';
124252
component.formData.email = 'john.doe@gmail.com';
125253
component.formData.phone = '';
@@ -132,6 +260,15 @@ describe('BudgetApplicationFormComponent', () => {
132260
});
133261

134262
it('should display an error message when phone is not a string', () => {
263+
mockBudgetStateService.services.set([
264+
{
265+
title: 'SEO',
266+
description: 'SEO service',
267+
price: 300,
268+
selected: true,
269+
},
270+
]);
271+
mockBudgetStateService.total.set(300);
135272
// @ts-ignore
136273
component.formData.phone = 123;
137274
component.formData.name = 'John Doe';
@@ -145,6 +282,15 @@ describe('BudgetApplicationFormComponent', () => {
145282
});
146283

147284
it('should display an error message when phone does not contain only numbers', () => {
285+
mockBudgetStateService.services.set([
286+
{
287+
title: 'SEO',
288+
description: 'SEO service',
289+
price: 300,
290+
selected: true,
291+
},
292+
]);
293+
mockBudgetStateService.total.set(300);
148294
component.formData.name = 'John Doe';
149295
component.formData.email = 'john.doe@gmail.com';
150296
component.formData.phone = '123a';
@@ -157,6 +303,15 @@ describe('BudgetApplicationFormComponent', () => {
157303
});
158304

159305
it('should display an error message when phone does not contain enough characters', () => {
306+
mockBudgetStateService.services.set([
307+
{
308+
title: 'SEO',
309+
description: 'SEO service',
310+
price: 300,
311+
selected: true,
312+
},
313+
]);
314+
mockBudgetStateService.total.set(300);
160315
component.formData.name = 'John Doe';
161316
component.formData.email = 'john.doe@gmail.com';
162317
component.formData.phone = '123';
@@ -171,6 +326,15 @@ describe('BudgetApplicationFormComponent', () => {
171326
});
172327

173328
it('should display an error message when phone does contain too many characters', () => {
329+
mockBudgetStateService.services.set([
330+
{
331+
title: 'SEO',
332+
description: 'SEO service',
333+
price: 300,
334+
selected: true,
335+
},
336+
]);
337+
mockBudgetStateService.total.set(300);
174338
component.formData.name = 'John Doe';
175339
component.formData.email = 'john.doe@gmail.com';
176340
component.formData.phone = '1234567890154545';

src/app/budget-application-form/budget-application-form.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class BudgetApplicationFormComponent {
1616
budgetListService = inject(BudgetListService);
1717
budgetStateService = inject(BudgetStateService);
1818

19-
private services: BudgetService[] = [];
19+
private _services: BudgetService[] = [];
2020
ERROR_MESSAGES = ERROR_MESSAGES;
2121

2222
errorStatusMessage = signal<string | undefined>(undefined);
@@ -36,14 +36,14 @@ export class BudgetApplicationFormComponent {
3636
}
3737

3838
private manageServices() {
39-
this.services = [];
39+
this._services = [];
4040
this.budgetStateService.services().forEach((service) => {
4141
if (service.selected) {
4242
let newService = {
4343
title: service.title,
4444
secondaryServices: service.secondaryServices,
4545
};
46-
this.services.push(newService);
46+
this._services.push(newService);
4747
}
4848
});
4949
}
@@ -54,7 +54,7 @@ export class BudgetApplicationFormComponent {
5454
name: this.formData.name,
5555
email: this.formData.email,
5656
phone: this.formData.phone,
57-
budgetServices: this.services,
57+
budgetServices: this._services,
5858
total: this.budgetStateService.total(),
5959
});
6060
this.getErrorStatus();

0 commit comments

Comments
 (0)