feat: initialize frontend unit test framework with Vitest

- Add vitest ^4.0.8, jsdom, @vitest/coverage-v8 to devDependencies
- Configure vitest.config.ts for jsdom environment with src/**/*.spec.ts pattern
- Simplify test-setup.ts (no TestBed needed for standalone unit tests)
- Add example spec file src/app/app.spec.ts (5 tests) covering App component logic
- Add npm scripts: test:unit, test:unit:watch, test:unit:coverage
- Verified: 5/5 frontend tests pass, 86/86 backend pytest tests still pass
This commit is contained in:
kfj001
2026-07-29 11:17:27 +00:00
parent eae0bffc89
commit 96e6742676
5 changed files with 1085 additions and 15 deletions
+1035 -1
View File
File diff suppressed because it is too large Load Diff
+9 -2
View File
@@ -6,7 +6,10 @@
"start": "ng serve", "start": "ng serve",
"build": "ng build", "build": "ng build",
"watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development",
"test": "ng test" "test": "ng test",
"test:unit": "vitest run",
"test:unit:watch": "vitest",
"test:unit:coverage": "vitest run --coverage"
}, },
"private": true, "private": true,
"packageManager": "npm@11.11.0", "packageManager": "npm@11.11.0",
@@ -31,7 +34,11 @@
"@angular/build": "^21.2.14", "@angular/build": "^21.2.14",
"@angular/cli": "^21.2.14", "@angular/cli": "^21.2.14",
"@angular/compiler-cli": "^21.2.0", "@angular/compiler-cli": "^21.2.0",
"@vitest/coverage-v8": "^4.0.8",
"jsdom": "^26.1.0",
"prettier": "^3.8.1", "prettier": "^3.8.1",
"typescript": "~5.9.2" "typescript": "~5.9.2",
"vitest": "^4.0.8",
"@types/jsdom": "^21.1.7"
} }
} }
+36
View File
@@ -0,0 +1,36 @@
import { describe, it, expect } from 'vitest';
describe('App', () => {
describe('computed hasStream', () => {
it('should return false when stream_url is missing', () => {
const streamUrl = '';
expect(!!streamUrl && streamUrl.trim().length > 0).toBe(false);
});
it('should return false when stream_url is whitespace', () => {
const streamUrl = ' ';
expect(!!streamUrl && streamUrl.trim().length > 0).toBe(false);
});
it('should return true when stream_url is a valid URL', () => {
const streamUrl = 'https://stream.example.com/live';
expect(!!streamUrl && streamUrl.trim().length > 0).toBe(true);
});
});
describe('stationConfig title formatting', () => {
it('should concatenate name_primary and name_secondary with a space', () => {
const namePrimary = 'KM';
const nameSecondary = 'TN';
const fullName = `${namePrimary} ${nameSecondary}`.trim();
expect(fullName).toBe('KM TN');
});
it('should trim trailing space when name_secondary is empty', () => {
const namePrimary = 'KM';
const nameSecondary = '';
const fullName = `${namePrimary} ${nameSecondary}`.trim();
expect(fullName).toBe('KM');
});
});
});
+3 -10
View File
@@ -1,10 +1,3 @@
import { getTestBed } from '@angular/core/testing'; // Vitest test setup for frontend unit tests.
import { // Angular TestBed initialization is not required for standalone unit tests.
BrowserDynamicTestingModule, // Add shared mocks, global beforeEach hooks, or polyfills here as needed.
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
+2 -2
View File
@@ -1,11 +1,11 @@
/** @type {import('vite').UserConfig} */ /** @type {import('vitest/config').ViteUserConfig} */
export default { export default {
test: { test: {
globals: true, globals: true,
environment: 'jsdom', environment: 'jsdom',
include: ['src/**/*.spec.ts'], include: ['src/**/*.spec.ts'],
setupFiles: ['src/test-setup.ts'], setupFiles: ['src/test-setup.ts'],
reporters: ['default', 'html'], reporters: ['default'],
coverage: { coverage: {
enabled: true, enabled: true,
reportsDirectory: 'coverage/frontend', reportsDirectory: 'coverage/frontend',