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",
"build": "ng build",
"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,
"packageManager": "npm@11.11.0",
@@ -31,7 +34,11 @@
"@angular/build": "^21.2.14",
"@angular/cli": "^21.2.14",
"@angular/compiler-cli": "^21.2.0",
"@vitest/coverage-v8": "^4.0.8",
"jsdom": "^26.1.0",
"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';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
// Vitest test setup for frontend unit tests.
// Angular TestBed initialization is not required for standalone unit tests.
// Add shared mocks, global beforeEach hooks, or polyfills here as needed.
+2 -2
View File
@@ -1,11 +1,11 @@
/** @type {import('vite').UserConfig} */
/** @type {import('vitest/config').ViteUserConfig} */
export default {
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.spec.ts'],
setupFiles: ['src/test-setup.ts'],
reporters: ['default', 'html'],
reporters: ['default'],
coverage: {
enabled: true,
reportsDirectory: 'coverage/frontend',