fix(pda): 修复海外PDA真机作业并固定APK与热更新发布流程
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { parse, compileTemplate } from '@vue/compiler-sfc'
|
||||
import {
|
||||
PDA_AUTHORITY, PDA_ROLE, loadLoginPreference, saveLoginPreference,
|
||||
restoreSession, session, signInWithTokens, signOut
|
||||
} from '../src/stores/session.js'
|
||||
|
||||
const source = readFileSync(new URL('../src/pages/login/login.vue', import.meta.url), 'utf8')
|
||||
const { descriptor, errors } = parse(source)
|
||||
const preferenceKey = 'overseas-pda-login-account-preference'
|
||||
|
||||
function storage() {
|
||||
const values = new Map()
|
||||
globalThis.uni = {
|
||||
setStorageSync: (key, value) => values.set(key, JSON.parse(JSON.stringify(value))),
|
||||
getStorageSync: (key) => values.get(key),
|
||||
removeStorageSync: (key) => values.delete(key),
|
||||
reLaunch() {}
|
||||
}
|
||||
signOut()
|
||||
return values
|
||||
}
|
||||
|
||||
function tokens() {
|
||||
const claims = {
|
||||
user_id: 42, membership_id: 84, tenant_id: 0, app_code: 'PLATFORM',
|
||||
overseas_warehouse_id: 900, exp: Math.floor(Date.now() / 1000) + 3600
|
||||
}
|
||||
return {
|
||||
accessToken: `header.${Buffer.from(JSON.stringify(claims)).toString('base64url')}.signature`,
|
||||
refreshToken: 'refresh-42', roles: [PDA_ROLE], authorities: [PDA_AUTHORITY]
|
||||
}
|
||||
}
|
||||
|
||||
function page(overrides = {}) {
|
||||
const dependencies = {
|
||||
DEV_LOGIN: { username: '', password: '' }, session, restoreSession, signInWithTokens,
|
||||
loadLoginPreference, saveLoginPreference, requireOnline() {},
|
||||
loginRequest: async () => tokens(), console: { error() {} }, ...overrides
|
||||
}
|
||||
const script = descriptor.script.content.replace(/^\s*import .*$/gm, '').replace('export default', 'return')
|
||||
const definition = new Function(...Object.keys(dependencies), script)(...Object.values(dependencies))
|
||||
const vm = definition.data()
|
||||
for (const [name, method] of Object.entries(definition.methods)) vm[name] = method.bind(vm)
|
||||
definition.onLoad.call(vm)
|
||||
return vm
|
||||
}
|
||||
|
||||
test('login template compiles with an account switch and separate row and switch events', () => {
|
||||
assert.deepEqual(errors, [])
|
||||
const compiled = compileTemplate({ source: descriptor.template.content, filename: 'login.vue', id: 'login' })
|
||||
assert.deepEqual(compiled.errors, [])
|
||||
assert.match(descriptor.template.content, /@tap="toggleRememberAccount"/)
|
||||
assert.match(descriptor.template.content, /<switch[^>]*:checked="rememberAccount"[^>]*@change="handleRememberChange"[^>]*@tap\.stop/)
|
||||
})
|
||||
|
||||
test('new installations default to remembering the account and an empty login form', () => {
|
||||
storage()
|
||||
assert.deepEqual(loadLoginPreference(), { rememberAccount: true, account: '' })
|
||||
const vm = page()
|
||||
assert.equal(vm.rememberAccount, true)
|
||||
assert.deepEqual(vm.form, { userId: '', password: '' })
|
||||
})
|
||||
|
||||
test('successful login remembers the trimmed account across sign out and page reopening', async () => {
|
||||
const values = storage()
|
||||
let credentials
|
||||
const vm = page({ loginRequest: async (...args) => { credentials = args; return tokens() } })
|
||||
vm.form = { userId: ' picker-42 ', password: 'test-password' }
|
||||
await vm.login()
|
||||
assert.equal(vm.error, '')
|
||||
assert.deepEqual(credentials, ['picker-42', 'test-password'])
|
||||
assert.deepEqual(values.get(preferenceKey), { rememberAccount: true, account: 'picker-42' })
|
||||
assert.equal(session.currentUser.id, '42')
|
||||
signOut()
|
||||
const reopened = page()
|
||||
assert.equal(reopened.form.userId, 'picker-42')
|
||||
assert.equal(reopened.form.password, '')
|
||||
assert.equal(reopened.rememberAccount, true)
|
||||
})
|
||||
|
||||
test('switch and row can each clear the saved account immediately without logging in', () => {
|
||||
storage()
|
||||
saveLoginPreference(true, 'picker-42')
|
||||
const vm = page()
|
||||
vm.handleRememberChange({ detail: { value: false } })
|
||||
assert.equal(vm.rememberAccount, false)
|
||||
assert.deepEqual(loadLoginPreference(), { rememberAccount: false, account: '' })
|
||||
assert.equal(page().form.userId, '')
|
||||
assert.equal(page().rememberAccount, false)
|
||||
vm.toggleRememberAccount()
|
||||
saveLoginPreference(true, 'picker-42')
|
||||
vm.toggleRememberAccount()
|
||||
assert.equal(vm.rememberAccount, false)
|
||||
assert.deepEqual(loadLoginPreference(), { rememberAccount: false, account: '' })
|
||||
})
|
||||
|
||||
test('login with remembering disabled leaves the next login form empty', async () => {
|
||||
storage()
|
||||
const vm = page()
|
||||
vm.toggleRememberAccount()
|
||||
vm.form = { userId: 'picker-42', password: 'test-password' }
|
||||
await vm.login()
|
||||
assert.equal(vm.error, '')
|
||||
assert.equal(session.currentUser.id, '42')
|
||||
signOut()
|
||||
const reopened = page()
|
||||
assert.equal(reopened.rememberAccount, false)
|
||||
assert.deepEqual(reopened.form, { userId: '', password: '' })
|
||||
})
|
||||
|
||||
test('failed authentication and rejected operator tokens preserve the last successful account', async () => {
|
||||
storage()
|
||||
saveLoginPreference(true, 'previous-picker')
|
||||
for (const loginRequest of [
|
||||
async () => { throw new Error('密码错误') },
|
||||
async () => ({ ...tokens(), authorities: [] })
|
||||
]) {
|
||||
const vm = page({ loginRequest })
|
||||
vm.form = { userId: 'other-picker', password: 'test-password' }
|
||||
await vm.login()
|
||||
assert.ok(vm.error)
|
||||
assert.equal(vm.submitting, false)
|
||||
assert.equal(session.currentUser, null)
|
||||
assert.deepEqual(loadLoginPreference(), { rememberAccount: true, account: 'previous-picker' })
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user