Skip to content

Commit 7a48b95

Browse files
L-X-Tclaude
andcommitted
test: repair test infrastructure, add lib unit tests and CI
The karma setup had been broken since the v20/v21 builder migrations and no test target existed for the library itself. Infrastructure: - remove the removed @angular-devkit/build-angular karma framework/ plugin from all karma.conf.js files - pass polyfills as array to @angular/build:karma (sample, quickstart-demo) - add karma-coverage required by the new builder's default plugin set - drop reference to non-existent src/test.ts from lib tsconfig.spec Tests: - add a test target for the lib plus its first unit tests: UrlHelperService parsing and DefaultHashHandler sha-256 against a known vector - add JwksValidationHandler guard-clause specs (suite was empty) - rewrite the stale quickstart scaffold specs: boot the components with the real OAuth providers and assert the discovery document request via HttpTestingController CI: - add npm run test:ci running all five suites headless single-run - add GitHub Actions workflow building lib, jwks and sample and running test:ci on pushes to master and pull requests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent d5d2bf9 commit 7a48b95

14 files changed

Lines changed: 380 additions & 36 deletions

File tree

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
8+
jobs:
9+
build-and-test:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- uses: actions/setup-node@v4
15+
with:
16+
node-version: 22
17+
cache: npm
18+
19+
- name: Install dependencies
20+
run: npm ci --legacy-peer-deps
21+
22+
- name: Build library
23+
run: npx ng build lib --configuration production
24+
25+
- name: Build angular-oauth2-oidc-jwks
26+
run: npx ng build angular-oauth2-oidc-jwks --ts-config tsconfig.npm.json
27+
28+
- name: Build sample app
29+
run: npx ng build sample
30+
31+
- name: Run unit tests
32+
run: npm run test:ci

angular.json

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@
3030
"projects/lib/**/*.html"
3131
]
3232
}
33+
},
34+
"test": {
35+
"builder": "@angular/build:karma",
36+
"options": {
37+
"polyfills": [
38+
"zone.js",
39+
"zone.js/testing"
40+
],
41+
"tsConfig": "projects/lib/tsconfig.spec.json",
42+
"karmaConfig": "projects/lib/karma.conf.js"
43+
}
3344
}
3445
}
3546
},
@@ -112,7 +123,9 @@
112123
"builder": "@angular/build:karma",
113124
"options": {
114125
"main": "projects/sample/src/test.ts",
115-
"polyfills": "projects/sample/src/polyfills.ts",
126+
"polyfills": [
127+
"projects/sample/src/polyfills.ts"
128+
],
116129
"tsConfig": "projects/sample/tsconfig.spec.json",
117130
"karmaConfig": "projects/sample/karma.conf.js",
118131
"styles": [
@@ -152,7 +165,9 @@
152165
"projects/quickstart-demo/src/favicon.ico",
153166
"projects/quickstart-demo/src/assets"
154167
],
155-
"styles": ["projects/quickstart-demo/src/styles.css"],
168+
"styles": [
169+
"projects/quickstart-demo/src/styles.css"
170+
],
156171
"scripts": [],
157172
"extractLicenses": false,
158173
"sourceMap": true,
@@ -206,14 +221,18 @@
206221
"builder": "@angular/build:karma",
207222
"options": {
208223
"main": "projects/quickstart-demo/src/test.ts",
209-
"polyfills": "projects/quickstart-demo/src/polyfills.ts",
224+
"polyfills": [
225+
"projects/quickstart-demo/src/polyfills.ts"
226+
],
210227
"tsConfig": "projects/quickstart-demo/tsconfig.spec.json",
211228
"karmaConfig": "projects/quickstart-demo/karma.conf.js",
212229
"assets": [
213230
"projects/quickstart-demo/src/favicon.ico",
214231
"projects/quickstart-demo/src/assets"
215232
],
216-
"styles": ["projects/quickstart-demo/src/styles.css"],
233+
"styles": [
234+
"projects/quickstart-demo/src/styles.css"
235+
],
217236
"scripts": []
218237
}
219238
}
@@ -364,7 +383,9 @@
364383
},
365384
"cli": {
366385
"analytics": false,
367-
"schematicCollections": ["@angular-eslint/schematics"],
386+
"schematicCollections": [
387+
"@angular-eslint/schematics"
388+
],
368389
"packageManager": "npm"
369390
}
370391
}

package-lock.json

Lines changed: 95 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"build": "npm run prettier && ng build --configuration production --project lib && npm run copy:readme && npm run copy:license && npm run docs",
1010
"build:jwks": "npm run prettier && ng build angular-oauth2-oidc-jwks --ts-config tsconfig.npm.json && npm run copyfiles:jwks",
1111
"test": "ng test",
12+
"test:ci": "ng test lib --watch=false --browsers=ChromeHeadless && ng test sample --watch=false --browsers=ChromeHeadless && ng test quickstart-demo --watch=false --browsers=ChromeHeadless && ng test quickstart-standalone --watch=false --browsers=ChromeHeadless && ng test angular-oauth2-oidc-jwks --watch=false --browsers=ChromeHeadless",
1213
"lint": "ng lint lib",
1314
"e2e": "ng e2e",
1415
"tsc": "tsc",
@@ -74,6 +75,7 @@
7475
"karma": "~6.4.4",
7576
"karma-chrome-launcher": "~3.2.0",
7677
"karma-cli": "~2.0.0",
78+
"karma-coverage": "~2.2.1",
7779
"karma-coverage-istanbul-reporter": "~3.0.3",
7880
"karma-jasmine": "~4.0.2",
7981
"karma-jasmine-html-reporter": "^1.7.0",

projects/angular-oauth2-oidc-jwks/karma.conf.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
module.exports = function(config) {
55
config.set({
66
basePath: '',
7-
frameworks: ['jasmine', '@angular-devkit/build-angular'],
7+
frameworks: ['jasmine'],
88
plugins: [
99
require('karma-jasmine'),
1010
require('karma-chrome-launcher'),
1111
require('karma-jasmine-html-reporter'),
12-
require('karma-coverage-istanbul-reporter'),
13-
require('@angular-devkit/build-angular/plugins/karma')
12+
require('karma-coverage-istanbul-reporter')
13+
1414
],
1515
client: {
1616
clearContext: false // leave Jasmine Spec Runner output visible in browser
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { AbstractValidationHandler, ValidationParams } from 'angular-oauth2-oidc';
2+
import { JwksValidationHandler } from './jwks-validation-handler';
3+
4+
describe('JwksValidationHandler', () => {
5+
let handler: JwksValidationHandler;
6+
7+
beforeEach(() => {
8+
handler = new JwksValidationHandler();
9+
});
10+
11+
it('should be created', () => {
12+
expect(handler).toBeTruthy();
13+
expect(handler instanceof AbstractValidationHandler).toBe(true);
14+
});
15+
16+
it('should allow the common JOSE signing algorithms by default', () => {
17+
expect(handler.allowedAlgorithms).toContain('RS256');
18+
expect(handler.allowedAlgorithms).toContain('ES256');
19+
expect(handler.allowedAlgorithms).toContain('HS256');
20+
});
21+
22+
it('should throw if no idToken is given', () => {
23+
expect(() =>
24+
handler.validateSignature({} as ValidationParams)
25+
).toThrowError('Parameter idToken expected!');
26+
});
27+
28+
it('should throw if no idTokenHeader is given', () => {
29+
expect(() =>
30+
handler.validateSignature({ idToken: 'abc' } as ValidationParams)
31+
).toThrowError('Parameter idTokenHandler expected.');
32+
});
33+
34+
it('should throw if no jwks is given', () => {
35+
expect(() =>
36+
handler.validateSignature({
37+
idToken: 'abc',
38+
idTokenHeader: { alg: 'RS256' },
39+
} as ValidationParams)
40+
).toThrowError('Parameter jwks expected!');
41+
});
42+
43+
it('should throw if jwks contains no keys', () => {
44+
expect(() =>
45+
handler.validateSignature({
46+
idToken: 'abc',
47+
idTokenHeader: { alg: 'RS256' },
48+
jwks: { keys: [] },
49+
} as unknown as ValidationParams)
50+
).toThrowError('Array keys in jwks missing!');
51+
});
52+
});

projects/lib/karma.conf.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
module.exports = function(config) {
55
config.set({
66
basePath: '',
7-
frameworks: ['jasmine', '@angular-devkit/build-angular'],
7+
frameworks: ['jasmine'],
88
plugins: [
99
require('karma-jasmine'),
1010
require('karma-chrome-launcher'),
1111
require('karma-jasmine-html-reporter'),
12-
require('karma-coverage-istanbul-reporter'),
13-
require('@angular-devkit/build-angular/plugins/karma')
12+
require('karma-coverage-istanbul-reporter')
13+
1414
],
1515
client: {
1616
clearContext: false // leave Jasmine Spec Runner output visible in browser
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { DefaultHashHandler } from './hash-handler';
2+
3+
function toHex(rawHash: string): string {
4+
return Array.from(rawHash)
5+
.map((c) => c.charCodeAt(0).toString(16).padStart(2, '0'))
6+
.join('');
7+
}
8+
9+
describe('DefaultHashHandler', () => {
10+
let handler: DefaultHashHandler;
11+
12+
beforeEach(() => {
13+
handler = new DefaultHashHandler();
14+
});
15+
16+
it('should calculate the correct sha-256 hash for a known vector', async () => {
17+
const hash = await handler.calcHash('abc', 'sha-256');
18+
expect(toHex(hash)).toEqual(
19+
'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
20+
);
21+
});
22+
23+
it('should return a 32 byte hash', async () => {
24+
const hash = await handler.calcHash('some-nonce-value', 'sha-256');
25+
expect(hash.length).toBe(32);
26+
});
27+
28+
it('should be deterministic', async () => {
29+
const a = await handler.calcHash('value', 'sha-256');
30+
const b = await handler.calcHash('value', 'sha-256');
31+
expect(a).toEqual(b);
32+
});
33+
34+
it('should produce different hashes for different inputs', async () => {
35+
const a = await handler.calcHash('value-a', 'sha-256');
36+
const b = await handler.calcHash('value-b', 'sha-256');
37+
expect(a).not.toEqual(b);
38+
});
39+
});

0 commit comments

Comments
 (0)