add test workflow (#38)

This commit is contained in:
Nebel 2024-03-16 16:32:53 +09:00 committed by GitHub
parent 9453697089
commit e90f9a9d46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 194 additions and 0 deletions

31
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,31 @@
name: test
on: pull_request
jobs:
test:
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run tests
shell: bash
run: BASE_URL="https://$(echo "${HEAD_REF}" | sed s/[^_0-9a-z]/-/gi).jwk.pages.dev/" npm test
env:
HEAD_REF: ${{ github.head_ref }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: "playwright-report-${{ matrix.os }}"
path: playwright-report

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
node_modules
dist
playwright-report
test-results

76
package-lock.json generated
View file

@ -10,6 +10,8 @@
"license": "MIT",
"devDependencies": {
"@exampledev/new.css": "^1.1.3",
"@playwright/test": "^1.42.1",
"@types/node": "^20.11.28",
"esbuild": "^0.20.0",
"jose": "^5.0.0"
}
@ -388,6 +390,30 @@
"integrity": "sha512-qhbGfqBRwUlM6MCSaJdUfjq86opNCMvM+6kVvs6S0kYhy0V8dKbe4rDMIklEJGuMc5QH5OuPjdCReu9I0tim2w==",
"dev": true
},
"node_modules/@playwright/test": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz",
"integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==",
"dev": true,
"dependencies": {
"playwright": "1.42.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/@types/node": {
"version": "20.11.28",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz",
"integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/esbuild": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
@ -426,6 +452,20 @@
"@esbuild/win32-x64": "0.20.1"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/jose": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz",
@ -434,6 +474,42 @@
"funding": {
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/playwright": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz",
"integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==",
"dev": true,
"dependencies": {
"playwright-core": "1.42.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=16"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz",
"integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true
}
}
}

View file

@ -5,11 +5,14 @@
"author": "Kohei Watanabe <nebel@fogtype.com>",
"license": "MIT",
"scripts": {
"test": "playwright test",
"build": "esbuild --bundle --loader:.html=copy --outdir=dist src/*",
"start": "esbuild --bundle --loader:.html=copy --outdir=dist --servedir=dist src/*"
},
"devDependencies": {
"@exampledev/new.css": "^1.1.3",
"@playwright/test": "^1.42.1",
"@types/node": "^20.11.28",
"esbuild": "^0.20.0",
"jose": "^5.0.0"
}

39
playwright.config.ts Normal file
View file

@ -0,0 +1,39 @@
import { defineConfig, devices } from "@playwright/test";
const baseURL = process.env.BASE_URL ?? "http://127.0.0.1:8000";
export default defineConfig({
testDir: "tests",
fullyParallel: true,
forbidOnly: Boolean(process.env.CI),
timeout: 10_000,
retries: 2,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
use: {
baseURL,
trace: "on-first-retry",
video: "on-first-retry",
},
projects: [
{
name: "chromium",
use: devices["Desktop Chrome"],
},
{
name: "firefox",
use: devices["Desktop Firefox"],
},
{
name: "webkit",
use: devices["Desktop Safari"],
},
],
webServer: {
url: baseURL,
command: "npm start",
stdout: "ignore",
stderr: "ignore",
reuseExistingServer: true,
},
});

43
tests/jwk.test.ts Normal file
View file

@ -0,0 +1,43 @@
import { test, expect } from "@playwright/test";
// prettier-ignore
const properties = {
"ECDSA (ES256)": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"ECDSA (ES384)": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"ECDSA (ES512)": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"RSASSA-PKCS1-v1_5 (RS256)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSASSA-PKCS1-v1_5 (RS384)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSASSA-PKCS1-v1_5 (RS512)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSASSA-PSS (PS256)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSASSA-PSS (PS384)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSASSA-PSS (PS512)": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"ECDH-ES": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"ECDH-ES+A128KW": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"ECDH-ES+A192KW": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"ECDH-ES+A256KW": ["alg", "use", "kid", "kty", "crv", "x", "y", "d"],
"RSA-OAEP": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSA-OAEP-256": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSA-OAEP-384": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
"RSA-OAEP-512": ["alg", "use", "kid", "kty", "e", "n", "d", "p", "q", "dp", "dq", "qi"],
};
// prettier-ignore-end
for (const [algorithm, expected] of Object.entries(properties)) {
test(`${algorithm} has ${expected}`, async ({ page }) => {
await page.goto("/");
await page.getByLabel("Algorithm").selectOption({ label: algorithm });
await page.getByLabel("Generate").click();
const jwk = await page
.getByLabel("Private Key")
.getByText(/./)
.inputValue()
.then(JSON.parse);
for (const property of expected) {
expect(jwk).toHaveProperty(property, expect.stringMatching(/./));
}
expect(Object.keys(jwk)).toHaveLength(expected.length);
});
}