This commit is contained in:
2026-10-19 01:06:27 +07:00
parent 7fa0004ab9
commit 4ef830a3b5
3 changed files with 104 additions and 0 deletions
+1
View File
@@ -392,6 +392,7 @@ app
)
await online.initialize()
if (quitting || startupWindow.isDestroyed()) return
void online.restoreGames()
let previousConnection = online.state.connection
const logConnection = () => {
const status = online!.state.connection
+91
View File
@@ -938,6 +938,97 @@ test('вход, подготовка и зашифрованные секрет
assert.equal(c.state.channels.main.desired, 'playing')
})
test('без сохранённого входа запуск не запрашивает список игр', async (t) => {
const f = await fixture(t)
await f.online.restoreGames()
assert.equal(f.requests.length, 0)
})
for (const expired of [false, true]) {
test(`после восстановления входа список игр загружается без кнопки; токен просрочен: ${expired}`, async (t) => {
const f = await fixture(t)
await f.login()
await f.online.close()
f.requests.length = 0
f.model.accessExpired = expired
const restored = new Online(
join(f.directory, 'connection'), f.store, new Controller(() => {}), f.secrets, f.fetchAPI,
)
t.after(() => restored.close())
await restored.initialize()
await restored.restoreGames()
assert.deepEqual(restored.snapshot().games, [{ id: 7, name: 'Дело', status: 'finish' }])
assert.equal(restored.snapshot().error, '')
assert.equal(restored.snapshot().busy, false)
assert.equal(restored.snapshot().screenId, null)
assert.equal(f.model.refreshCalls, expired ? 1 : 0)
assert.ok(f.requests.every(r => ['/api/games', '/api/auth/refresh'].includes(r.path)))
})
}
test('запуск без сети сохраняет доступ к локальной игре; список можно обновить позже', async (t) => {
const f = await fixture(t)
await f.login()
await f.online.act({ action: 'select-game', gameId: 7 })
await f.online.close()
f.model.offline = true
const controller = new Controller(() => {})
const restored = new Online(
join(f.directory, 'connection'), f.store, controller, f.secrets, f.fetchAPI,
)
t.after(() => restored.close())
await restored.initialize()
const selected = controller.state.catalog.key
assert.ok(selected)
await restored.restoreGames()
assert.match(restored.snapshot().error, /Сервер недоступен/)
assert.equal(restored.snapshot().busy, false)
controller.output(true)
assert.equal(controller.state.outputOpen, true)
assert.equal(controller.state.catalog.key, selected)
f.model.offline = false
await restored.act({ action: 'games' })
assert.equal(restored.snapshot().games.length, 1)
assert.equal(restored.snapshot().error, '')
})
for (const fails of [false, true]) {
test(`ответ фоновой загрузки после выхода игнорируется; ошибка: ${fails}`, async (t) => {
const f = await fixture(t)
await f.login()
await f.online.close()
let release!: () => void
let started!: () => void
const gate = new Promise<void>(resolve => { release = resolve })
const requestStarted = new Promise<void>(resolve => { started = resolve })
const fetchAPI: typeof fetch = async (input, init) => {
const response = await f.fetchAPI(input, init)
const read = response.json.bind(response)
response.json = async () => {
started()
await gate
if (fails) throw new Error('network failure')
return read()
}
return response
}
const restored = new Online(
join(f.directory, 'connection'), f.store, new Controller(() => {}), f.secrets, fetchAPI,
)
t.after(() => restored.close())
await restored.initialize()
const pending = restored.restoreGames()
await requestStarted
assert.equal(restored.snapshot().busy, false)
await restored.act({ action: 'logout' })
release()
await pending
assert.equal(restored.snapshot().authenticated, false)
assert.deepEqual(restored.snapshot().games, [])
assert.equal(restored.snapshot().error, '')
})
}
test('без хранилища ОС вход только в памяти; выход не останавливает показ', async (t) => {
const f = await fixture(t, false)
await f.prepare()
+12
View File
@@ -1668,8 +1668,20 @@ export class Online {
await this.refreshMaterials()
await this.poll()
}
async restoreGames() {
if (!this.credentials) return
const generation = this.generation
try {
await this.loadGames()
} catch (error) {
if (generation === this.generation && !this.state.error)
this.state.error = error instanceof Error ? error.message : 'Не удалось загрузить список игр'
}
}
private async loadGames() {
const generation = this.generation
const result = await this.client().GetGames({})
if (generation !== this.generation) throw new SessionChangedError()
if (!Array.isArray(result.games ?? [])) throw new Error('Некорректный список игр')
this.state.games = ((result.games ?? []) as unknown[]).map((value) => {
const g = object(value)