front-end-dev-standards 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/validate-package.js +10 -5
- package/standards//342/232/241 performance.md" +138 -0
- package/standards//360/237/205/260/357/270/217 angular.md" +571 -0
- package/standards//360/237/216/250 ui-ux.md" +391 -0
- package/standards//360/237/223/232 documentation.md" +127 -0
- package/standards//360/237/224/214 api-standards.md" +201 -0
- package/standards//360/237/224/220 security.md" +432 -0
- package/standards//360/237/232/200 ci-cd.md" +134 -0
- package/standards//360/237/244/226 ai-development.md" +142 -0
- package/standards//360/237/247/221/342/200/215/360/237/222/273 coding-style.md" +765 -0
- package/standards//360/237/247/252 testing.md" +399 -0
- package/standards//360/237/247/261 architecture.md" +654 -0
- package/standards/angular.md +0 -234
- package/standards/architecture.md +0 -263
- package/standards/coding-style.md +0 -223
- package/standards/security.md +0 -6
- package/standards/testing.md +0 -244
package/standards/security.md
DELETED
package/standards/testing.md
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# Testing Standards
|
|
2
|
-
|
|
3
|
-
> Unit and integration testing conventions for Angular applications using Vitest.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Test Stack
|
|
8
|
-
|
|
9
|
-
| Tool | Purpose |
|
|
10
|
-
|---|---|
|
|
11
|
-
| **Vitest** | Test runner (Angular 21 default) |
|
|
12
|
-
| **Angular TestBed** | Component/service integration |
|
|
13
|
-
| **ng-mocks** / manual stubs | Dependency mocking (when needed) |
|
|
14
|
-
|
|
15
|
-
Run tests:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm test
|
|
19
|
-
ng test
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## File Conventions
|
|
25
|
-
|
|
26
|
-
- Co-locate tests: `employee.service.ts` → `employee.service.spec.ts`
|
|
27
|
-
- Page tests: `employee-list.page.spec.ts`
|
|
28
|
-
- Place test utilities in `src/testing/` or feature `testing/` folder.
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Service Tests
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { TestBed } from '@angular/core/testing';
|
|
36
|
-
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
|
37
|
-
import { provideHttpClient } from '@angular/common/http';
|
|
38
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
39
|
-
|
|
40
|
-
import { EmployeeService } from './employee.service';
|
|
41
|
-
|
|
42
|
-
describe('EmployeeService', () => {
|
|
43
|
-
let service: EmployeeService;
|
|
44
|
-
let httpMock: HttpTestingController;
|
|
45
|
-
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
TestBed.configureTestingModule({
|
|
48
|
-
providers: [EmployeeService, provideHttpClient(), provideHttpClientTesting()],
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
service = TestBed.inject(EmployeeService);
|
|
52
|
-
httpMock = TestBed.inject(HttpTestingController);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
afterEach(() => {
|
|
56
|
-
httpMock.verify();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should fetch all employees', () => {
|
|
60
|
-
const mockEmployees = [{ id: '1', firstName: 'Jane', lastName: 'Doe', email: 'jane@co.com', departmentId: 'd1', createdAt: '2024-01-01' }];
|
|
61
|
-
|
|
62
|
-
service.getAll().subscribe(employees => {
|
|
63
|
-
expect(employees).toEqual(mockEmployees);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const req = httpMock.expectOne('/api/employees');
|
|
67
|
-
expect(req.request.method).toBe('GET');
|
|
68
|
-
req.flush(mockEmployees);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Service Test Rules
|
|
74
|
-
|
|
75
|
-
- Use `HttpTestingController` for HTTP services.
|
|
76
|
-
- Test success and error paths.
|
|
77
|
-
- Verify request method, URL, headers, and body.
|
|
78
|
-
- No real HTTP calls in unit tests.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Component Tests
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
86
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
87
|
-
|
|
88
|
-
import { EmployeeListPage } from './employee-list.page';
|
|
89
|
-
import { EmployeeService } from '../../services/employee.service';
|
|
90
|
-
import { of, throwError } from 'rxjs';
|
|
91
|
-
|
|
92
|
-
describe('EmployeeListPage', () => {
|
|
93
|
-
let fixture: ComponentFixture<EmployeeListPage>;
|
|
94
|
-
let component: EmployeeListPage;
|
|
95
|
-
let employeeService: { getAll: ReturnType<typeof vi.fn> };
|
|
96
|
-
|
|
97
|
-
beforeEach(async () => {
|
|
98
|
-
employeeService = { getAll: vi.fn().mockReturnValue(of([])) };
|
|
99
|
-
|
|
100
|
-
await TestBed.configureTestingModule({
|
|
101
|
-
imports: [EmployeeListPage],
|
|
102
|
-
providers: [{ provide: EmployeeService, useValue: employeeService }],
|
|
103
|
-
}).compileComponents();
|
|
104
|
-
|
|
105
|
-
fixture = TestBed.createComponent(EmployeeListPage);
|
|
106
|
-
component = fixture.componentInstance;
|
|
107
|
-
fixture.detectChanges();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should create', () => {
|
|
111
|
-
expect(component).toBeTruthy();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should display employees when loaded', () => {
|
|
115
|
-
const employees = [{ id: '1', firstName: 'Jane', lastName: 'Doe', email: 'j@co.com', departmentId: 'd1', createdAt: '2024-01-01' }];
|
|
116
|
-
employeeService.getAll.mockReturnValue(of(employees));
|
|
117
|
-
|
|
118
|
-
component.loadEmployees();
|
|
119
|
-
fixture.detectChanges();
|
|
120
|
-
|
|
121
|
-
expect(component.employees()).toEqual(employees);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should set error signal on failure', () => {
|
|
125
|
-
employeeService.getAll.mockReturnValue(throwError(() => new Error('Network error')));
|
|
126
|
-
|
|
127
|
-
component.loadEmployees();
|
|
128
|
-
fixture.detectChanges();
|
|
129
|
-
|
|
130
|
-
expect(component.error()).toBeTruthy();
|
|
131
|
-
expect(component.loading()).toBe(false);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Component Test Rules
|
|
137
|
-
|
|
138
|
-
- Import standalone component in `TestBed.configureTestingModule({ imports: [...] })`.
|
|
139
|
-
- Mock services — don't test service logic in component tests.
|
|
140
|
-
- Test signal state, not internal implementation details.
|
|
141
|
-
- Query DOM for user-visible behavior when testing templates.
|
|
142
|
-
- Use `fixture.detectChanges()` after state updates.
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## Testing Signals
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
it('should compute filtered employees', () => {
|
|
150
|
-
component.employees.set([
|
|
151
|
-
{ id: '1', firstName: 'Jane', /* ... */ },
|
|
152
|
-
{ id: '2', firstName: 'John', /* ... */ },
|
|
153
|
-
]);
|
|
154
|
-
component.searchTerm.set('Jane');
|
|
155
|
-
|
|
156
|
-
expect(component.filteredEmployees()).toHaveLength(1);
|
|
157
|
-
expect(component.filteredEmployees()[0].firstName).toBe('Jane');
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Prefer testing public signal values over private fields.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Test Naming
|
|
166
|
-
|
|
167
|
-
Use descriptive `it` blocks:
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
// Good
|
|
171
|
-
it('should disable submit button when form is invalid')
|
|
172
|
-
it('should redirect to login when auth guard rejects unauthenticated user')
|
|
173
|
-
|
|
174
|
-
// Bad
|
|
175
|
-
it('should work')
|
|
176
|
-
it('test submit')
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
Pattern: `should [expected behavior] when [condition]`
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## Coverage Expectations
|
|
184
|
-
|
|
185
|
-
| Layer | Minimum Coverage |
|
|
186
|
-
|---|---|
|
|
187
|
-
| Services (business/API) | 80%+ |
|
|
188
|
-
| Utility functions | 90%+ |
|
|
189
|
-
| Smart/Page components | 70%+ |
|
|
190
|
-
| Presentational components | Key interactions covered |
|
|
191
|
-
| Guards / Interceptors | 100% of branches |
|
|
192
|
-
|
|
193
|
-
Focus on **behavior coverage**, not line-count gaming.
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## What to Test
|
|
198
|
-
|
|
199
|
-
### Always Test
|
|
200
|
-
|
|
201
|
-
- Service HTTP calls (success + error)
|
|
202
|
-
- Form validation logic
|
|
203
|
-
- Guards and interceptors
|
|
204
|
-
- Complex computed signals
|
|
205
|
-
- User interactions (click, submit, navigation)
|
|
206
|
-
|
|
207
|
-
### Skip or Minimize
|
|
208
|
-
|
|
209
|
-
- Trivial getters with no logic
|
|
210
|
-
- Third-party library internals
|
|
211
|
-
- Static template text with no binding logic
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Test Data
|
|
216
|
-
|
|
217
|
-
Create factories in `testing/factories/`:
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
// testing/factories/employee.factory.ts
|
|
221
|
-
import { Employee } from '../../features/employees/models/employee.model';
|
|
222
|
-
|
|
223
|
-
export function createEmployee(overrides: Partial<Employee> = {}): Employee {
|
|
224
|
-
return {
|
|
225
|
-
id: 'emp-1',
|
|
226
|
-
firstName: 'Jane',
|
|
227
|
-
lastName: 'Doe',
|
|
228
|
-
email: 'jane.doe@company.com',
|
|
229
|
-
departmentId: 'dept-1',
|
|
230
|
-
createdAt: '2024-06-01T00:00:00.000Z',
|
|
231
|
-
...overrides,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
## Anti-Patterns
|
|
239
|
-
|
|
240
|
-
- ❌ Testing implementation details (private methods)
|
|
241
|
-
- ❌ Shared mutable state between tests
|
|
242
|
-
- ❌ `setTimeout` without fakeAsync / vi.useFakeTimers
|
|
243
|
-
- ❌ Snapshot testing for entire templates ( brittle )
|
|
244
|
-
- ❌ E2E tests disguised as unit tests
|