front-end-dev-standards 1.0.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.
@@ -0,0 +1,6 @@
1
+ # Security Standards
2
+
3
+ > Placeholder — auto-discovered by setup.js when you run standards:setup.
4
+
5
+ - Never commit secrets or API keys.
6
+ - Use environment variables for sensitive config.
@@ -0,0 +1,244 @@
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
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: Company Angular frontend coding standards — enforced for all AI-generated and reviewed code
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Company Frontend Standards (front-end-dev-standards v{{STANDARDS_VERSION}})
7
+
8
+ You are generating code for an enterprise Angular application. Follow these standards strictly.
9
+
10
+ > Auto-generated by front-end-dev-standards on {{GENERATED_AT}}.
11
+ > Do not edit this file manually unless your team owns custom overrides — use `.standardsrc.json` and re-run setup.
12
+
13
+ ## Standards Documents
14
+
15
+ Read and apply ALL of the following standards files in the project:
16
+
17
+ {{STANDARDS_PATHS}}
18
+
19
+ When standards conflict, priority order is:
20
+ 1. `angular.md` (framework-specific rules)
21
+ 2. `architecture.md` (structure and patterns)
22
+ 3. `coding-style.md` (naming and formatting)
23
+ 4. `testing.md` (test requirements)
24
+
25
+ ## Mandatory Angular Patterns (Angular 20+)
26
+
27
+ Always generate:
28
+
29
+ - **Standalone components** — no `NgModule` for new code
30
+ - **`inject()`** for dependency injection — never constructor injection
31
+ - **Signals** — `signal()`, `computed()`, `input()`, `output()` for state and bindings
32
+ - **`ChangeDetectionStrategy.OnPush`** on every component
33
+ - **Typed Reactive Forms** — `FormGroup<T>` with `nonNullable: true`
34
+ - **Angular Material** for UI components in enterprise apps
35
+ - **Feature-based folder structure** — see `architecture.md`
36
+ - **Native control flow** — `@if`, `@for`, `@switch` (not structural directives)
37
+ - **`track` in `@for` loops**
38
+
39
+ Never generate:
40
+
41
+ - ❌ `NgModule` declarations
42
+ - ❌ Constructor-based dependency injection
43
+ - ❌ `@Input()` / `@Output()` decorators (use signal inputs/outputs)
44
+ - ❌ `*ngIf`, `*ngFor`, `*ngSwitch`
45
+ - ❌ `BehaviorSubject` for simple component-local state
46
+ - ❌ Untyped forms or `any` without justification
47
+ - ❌ Business logic in templates
48
+ - ❌ Direct DOM manipulation
49
+
50
+ ## Architecture Quick Reference
51
+
52
+ ```
53
+ src/app/
54
+ core/ → guards, interceptors, app-wide services
55
+ shared/ → reusable UI components (no feature imports)
56
+ features/ → lazy-loaded business features
57
+ layout/ → app shell
58
+ ```
59
+
60
+ Each feature:
61
+
62
+ ```
63
+ features/<name>/
64
+ components/ → presentational
65
+ pages/ → smart/routable containers
66
+ services/ → API integration
67
+ models/ → TypeScript interfaces
68
+ <name>.routes.ts
69
+ ```
70
+
71
+ ## Code Generation Checklist
72
+
73
+ Before finishing any generated code, verify:
74
+
75
+ 1. Component is standalone with explicit `imports` array
76
+ 2. OnPush change detection is set
77
+ 3. Services use `inject()` and `providedIn: 'root'`
78
+ 4. HTTP calls are typed: `http.get<ResponseType>()`
79
+ 5. Errors are handled and surfaced to the user
80
+ 6. A co-located `*.spec.ts` file exists for services and pages
81
+ 7. File names use kebab-case; classes use PascalCase
82
+
83
+ ## Testing Requirements
84
+
85
+ When generating services or page components, also generate Vitest tests:
86
+
87
+ - Use `TestBed.configureTestingModule({ imports: [StandaloneComponent] })`
88
+ - Mock dependencies with `vi.fn()`
89
+ - Test success and error paths
90
+ - Use `HttpTestingController` for HTTP services
91
+
92
+ See `.ai-standards/testing.md` for full testing standards.
@@ -0,0 +1,92 @@
1
+ # GitHub Copilot Instructions
2
+
3
+ > Auto-generated by front-end-dev-standards v{{STANDARDS_VERSION}} on {{GENERATED_AT}}.
4
+
5
+ Follow the company Angular frontend standards defined in this repository.
6
+
7
+ ## Standards Location
8
+
9
+ {{STANDARDS_PATHS}}
10
+
11
+ Read these files before generating or suggesting code.
12
+
13
+ ## Required Patterns (Angular 20+)
14
+
15
+ When generating Angular code, ALWAYS use:
16
+
17
+ - Standalone components (no NgModules)
18
+ - `inject()` instead of constructor injection
19
+ - Signals: `signal()`, `computed()`, `input()`, `output()`
20
+ - `ChangeDetectionStrategy.OnPush`
21
+ - Typed Reactive Forms with `FormGroup<T>` and `nonNullable: true`
22
+ - Angular Material for UI
23
+ - Native control flow: `@if`, `@for`, `@switch`
24
+ - `track` expression in all `@for` loops
25
+ - Feature-based architecture under `src/app/features/`
26
+
27
+ ## Never Suggest
28
+
29
+ - NgModule-based components or declarations
30
+ - Constructor dependency injection
31
+ - `@Input()` / `@Output()` decorators (use signal-based APIs)
32
+ - `*ngIf`, `*ngFor`, `*ngSwitch` structural directives
33
+ - `BehaviorSubject` for simple UI state
34
+ - Untyped forms or `any` type
35
+ - Template-driven forms for complex forms
36
+ - Direct DOM access (`document.querySelector`, `ElementRef` manipulation)
37
+
38
+ ## File Structure
39
+
40
+ When creating new features:
41
+
42
+ ```
43
+ src/app/features/<feature-name>/
44
+ components/ # presentational components
45
+ pages/ # routable smart components (*.page.ts)
46
+ services/ # API services
47
+ models/ # TypeScript interfaces
48
+ <feature>.routes.ts
49
+ ```
50
+
51
+ ## Naming Conventions
52
+
53
+ - Files: `kebab-case` (e.g., `employee-list.component.ts`)
54
+ - Classes: `PascalCase` (e.g., `EmployeeListComponent`)
55
+ - Selectors: `app-` prefix (e.g., `app-employee-list`)
56
+ - Signals: descriptive nouns (`employees`, `loading`, `isValid`)
57
+
58
+ ## Testing
59
+
60
+ When suggesting tests, use Vitest with Angular TestBed:
61
+
62
+ - Co-locate: `*.spec.ts` next to source file
63
+ - Import standalone components in TestBed
64
+ - Mock services with `vi.fn()`
65
+ - Use `HttpTestingController` for HTTP testing
66
+
67
+ ## Example Component
68
+
69
+ ```typescript
70
+ import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
71
+ import { EmployeeService } from '../services/employee.service';
72
+ import { Employee } from '../models/employee.model';
73
+
74
+ @Component({
75
+ selector: 'app-employee-list',
76
+ imports: [],
77
+ templateUrl: './employee-list.component.html',
78
+ styleUrl: './employee-list.component.scss',
79
+ changeDetection: ChangeDetectionStrategy.OnPush,
80
+ })
81
+ export class EmployeeListComponent {
82
+ private readonly employeeService = inject(EmployeeService);
83
+
84
+ readonly employees = signal<Employee[]>([]);
85
+ readonly loading = signal(false);
86
+ }
87
+ ```
88
+
89
+ ## Priority
90
+
91
+ If unsure, prefer simpler signal-based standalone code over RxJS-heavy patterns.
92
+ Always match existing project conventions in neighboring files.