60 lines
3.4 KiB
JavaScript
60 lines
3.4 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] = await Promise.all([read('../pages/login/login.vue'), read('../api/http.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, /暂时无法恢复登录状态/)
|
|
})
|
|
|
|
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 revokes the refresh token without delaying local cleanup', async () => {
|
|
const [profile, auth] = await Promise.all([read('../pages/profile/profile.vue'), read('../api/auth.js')])
|
|
assert.match(auth, /export function logout\(refreshToken, accessToken\)/)
|
|
assert.match(profile, /const refreshToken = session\.refreshToken; const accessToken = session\.token; signOut\(\); uni\.reLaunch/)
|
|
assert.match(profile, /logoutRequest\(refreshToken, accessToken\)\.catch/)
|
|
})
|
|
|
|
test('development login remembers only the account preference, never the entered password', async () => {
|
|
const [login, session] = await Promise.all([read('../pages/login/login.vue'), read('../stores/session.js')])
|
|
assert.match(login, /form: \{ userId: 'platform_admin', password: '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\)/)
|
|
})
|