Files
pda-uniapp/tests/auth-session.test.mjs
T

80 lines
4.2 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
const read = (path) => readFile(new URL(path, import.meta.url), 'utf8')
test('authenticated PDA requests refresh once and replay once after unauthorized', async () => {
const http = await read('../api/http.js')
assert.match(http, /let refreshPromise = null/)
assert.match(http, /refreshPromise = \(async \(\) =>/)
assert.match(http, /session\.token && session\.token !== accessToken \? session\.token : await refreshAccessToken\(\)/)
assert.match(http, /response = await execute\(accessToken\)[\s\S]*?isUnauthorized\(response\)[\s\S]*?response = await execute\(accessToken\)/)
assert.match(http, /apiRequest/)
assert.match(http, /apiDownload/)
assert.match(http, /apiUpload/)
})
test('refresh rotation persists the complete token pair and preserves operator context', async () => {
const [session, auth] = await Promise.all([read('../stores/session.js'), read('../api/auth.js')])
assert.match(session, /export function updateTokenPair\(tokens\)/)
assert.match(session, /session\.refreshToken = tokens\.refreshToken/)
assert.match(session, /const previousUser = session\.currentUser \|\| \{\}/)
assert.match(session, /persistSession\(\)/)
assert.match(session, /isAccessTokenExpiring/)
assert.match(auth, /authRequest\('\/auth\/refresh', \{ refreshToken \}\)/)
})
test('app launch restores and validates persisted tokens before entering the workbench', async () => {
const [login, http, session] = await Promise.all([read('../pages/login/login.vue'), read('../api/http.js'), read('../stores/session.js')])
assert.match(login, /async onLoad\(\)[\s\S]*?restoreSession\(\)[\s\S]*?await ensureAccessToken\(\)[\s\S]*?pages\/home\/home/)
assert.match(http, /export function ensureAccessToken\(\)/)
assert.match(login, /暂时无法恢复登录状态/)
assert.match(session, /id: String\(claims\.user_id \?\? savedUser\.id \?\? ''\)/)
assert.match(session, /persistSession\(\)[\s\S]*?return true/)
})
test('JWT decoding preserves 19 digit identity claims exactly', async () => {
const { decodeAccessToken } = await import('../utils/jwt-claims.js')
const payload = Buffer.from(JSON.stringify({
app_code: 'PLATFORM',
user_id: 1,
tenant_id: '2101483345056575489',
exp: 4102444800
}).replace('"user_id":1', '"user_id":2100885001485500418')).toString('base64url')
const claims = decodeAccessToken(`header.${payload}.signature`)
assert.equal(claims.user_id, '2100885001485500418')
assert.equal(claims.tenant_id, '2101483345056575489')
assert.equal(claims.exp, 4102444800)
})
test('confirmed session expiry clears sensitive state and redirects only once', async () => {
const http = await read('../api/http.js')
assert.match(http, /observedRefreshToken !== session\.refreshToken/)
assert.match(http, /signOut\(\)[\s\S]*?redirectAfterSessionExpiry\(\)/)
assert.match(http, /if \(redirectingToLogin\) return/)
assert.match(http, /url: '\/pages\/login\/login'/)
assert.match(http, /if \(isUnauthorized\(error\)\) return expireSession/)
})
test('manual logout waits for captured-session revoke and honestly handles failure', async () => {
const [profile, helper] = await Promise.all([read('../pages/profile/profile.vue'), read('../api/logout-session.js')])
assert.match(profile, /logoutCurrentSession\(\)/)
assert.match(profile, /operation\.then/)
assert.match(profile, /服务端退出未确认/)
assert.match(helper, /signOut\(\)/)
assert.match(helper, /error\.statusCode !== 401/)
assert.doesNotMatch(profile, /catch\(\(\) => \{\}\)/)
})
test('production login starts empty and remembers only the account preference', async () => {
const [login, session] = await Promise.all([read('../pages/login/login.vue'), read('../stores/session.js')])
assert.match(login, /form: \{ userId: '', password: '' \}/)
assert.doesNotMatch(login, /platform_admin|ChangeMe123!/)
assert.match(session, /export function saveLoginPreference\(rememberAccount, account = ''\)/)
const savePreference = session.match(/export function saveLoginPreference[\s\S]*?\n\}/)?.[0] || ''
assert.match(savePreference, /account: rememberAccount/)
assert.doesNotMatch(savePreference, /password/)
assert.match(login, /if \(!this\.rememberAccount\) saveLoginPreference\(false\)/)
})