mirror of
https://github.com/hanzoai/openid-client.git
synced 2026-09-24 17:01:10 +00:00
188 lines
4.1 KiB
TypeScript
188 lines
4.1 KiB
TypeScript
import * as fs from 'node:fs/promises'
|
|
|
|
const {
|
|
SUITE_BASE_URL = 'https://www.certification.openid.net',
|
|
SUITE_ACCESS_TOKEN,
|
|
} = process.env
|
|
|
|
export interface ModulePrescription {
|
|
testModule: string
|
|
variant: null | Record<string, string>
|
|
skipLogTestFinished?: boolean
|
|
}
|
|
|
|
export interface Test {
|
|
id: string
|
|
name: string
|
|
url: string
|
|
}
|
|
|
|
export interface ModuleInfo {
|
|
status: string
|
|
result: string
|
|
}
|
|
|
|
export interface Plan {
|
|
id: string
|
|
name: string
|
|
modules: ModulePrescription[]
|
|
}
|
|
|
|
export interface PlanInfo {
|
|
certificationProfileName: string | null
|
|
}
|
|
|
|
function url(pathname: string, search?: Record<string, string>) {
|
|
const target = new URL(pathname, SUITE_BASE_URL)
|
|
target.search = new URLSearchParams(search).toString()
|
|
return target.href
|
|
}
|
|
|
|
function headers(headers?: Record<string, string>) {
|
|
const result = new Headers({ ...headers })
|
|
if (SUITE_ACCESS_TOKEN) {
|
|
result.set('authorization', `bearer ${SUITE_ACCESS_TOKEN}`)
|
|
}
|
|
return result
|
|
}
|
|
|
|
export async function createTestPlan(
|
|
planName: string,
|
|
config: Record<string, unknown>,
|
|
variant: Record<string, string>,
|
|
) {
|
|
const response = await fetch(
|
|
url('/api/plan', { planName, variant: JSON.stringify(variant) }),
|
|
{
|
|
method: 'POST',
|
|
headers: headers({ 'content-type': 'application/json;charset=utf-8' }),
|
|
body: JSON.stringify(config),
|
|
},
|
|
)
|
|
|
|
if (response.status !== 201) {
|
|
throw new Error(await response.text())
|
|
}
|
|
|
|
return (await response.json()) as Plan
|
|
}
|
|
|
|
export async function getTestPlanInfo(plan: Plan) {
|
|
const response = await fetch(url(`/api/plan/${plan.id}`), {
|
|
headers: headers(),
|
|
})
|
|
|
|
if (response.status !== 200) {
|
|
throw new Error(await response.text())
|
|
}
|
|
|
|
return (await response.json()) as PlanInfo
|
|
}
|
|
|
|
export async function getTestExposed(
|
|
test: Test,
|
|
): Promise<Record<string, string>> {
|
|
const response = await fetch(url(`/api/runner/${test.id}`), {
|
|
method: 'GET',
|
|
headers: headers(),
|
|
})
|
|
|
|
if (response.status !== 200) {
|
|
throw new Error(await response.text())
|
|
}
|
|
|
|
const { exposed = {} } = await response.json()
|
|
|
|
return exposed
|
|
}
|
|
|
|
export async function createTestFromPlan(
|
|
plan: Plan,
|
|
module: ModulePrescription,
|
|
) {
|
|
const search = { test: module.testModule, plan: plan.id }
|
|
|
|
if (module.variant) {
|
|
Object.assign(search, { variant: JSON.stringify(module.variant) })
|
|
}
|
|
|
|
const response = await fetch(url('/api/runner', search), {
|
|
method: 'POST',
|
|
headers: headers(),
|
|
})
|
|
|
|
if (response.status !== 201) {
|
|
throw new Error(await response.text())
|
|
}
|
|
|
|
const test: Test = await response.json()
|
|
|
|
await waitForState(test, { states: new Set(['WAITING']), results: new Set() })
|
|
|
|
return test
|
|
}
|
|
|
|
async function getModuleInfo(module: Test) {
|
|
const response = await fetch(url(`/api/info/${module.id}`), {
|
|
headers: headers(),
|
|
})
|
|
|
|
if (response.status !== 200) {
|
|
throw new Error(await response.text())
|
|
}
|
|
|
|
return (await response.json()) as ModuleInfo
|
|
}
|
|
|
|
export async function downloadArtifact(plan: Plan) {
|
|
const response = await fetch(url(`/api/plan/exporthtml/${plan.id}`), {
|
|
headers: headers(),
|
|
})
|
|
|
|
await fs.writeFile(
|
|
`${plan.id}.zip`,
|
|
new Uint8Array(await response.arrayBuffer()),
|
|
{ flag: 'w' },
|
|
)
|
|
}
|
|
|
|
export async function waitForState(
|
|
test: Test,
|
|
{
|
|
interval = 150,
|
|
timeout = 60_000,
|
|
states = new Set(['FINISHED']),
|
|
results = new Set(['REVIEW', 'PASSED', 'WARNING', 'SKIPPED']),
|
|
} = {},
|
|
) {
|
|
const timeoutAt = Date.now() + timeout
|
|
|
|
do {
|
|
const { status, result } = await getModuleInfo(test)
|
|
if (states.has(status)) {
|
|
if (results.size) {
|
|
if (!status || !result) continue
|
|
if (!results.has(result)) {
|
|
throw new Error(`module id ${test.id} is ${status} but ${result}`)
|
|
}
|
|
} else {
|
|
if (!status) continue
|
|
}
|
|
|
|
return [status, result]
|
|
}
|
|
|
|
if (status === 'INTERRUPTED') {
|
|
throw new Error(`module id ${test.id} is ${status}`)
|
|
}
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, interval))
|
|
} while (Date.now() < timeoutAt)
|
|
|
|
throw new Error(
|
|
`Timed out waiting for test module ${test.id} to be in one of states: ${[
|
|
...states,
|
|
].join(', ')}`,
|
|
)
|
|
}
|