| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- import { expect, test } from '@playwright/test'
- import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
- import { tmpdir } from 'node:os'
- import { join } from 'node:path'
- import { pathToFileURL } from 'node:url'
- import { once } from 'node:events'
- import type { AddressInfo } from 'node:net'
- import serve from 'koa-static'
- import send from 'koa-send'
- test('opens settings and schedules an independent Web update while all 9119 requests fail', async ({ page }, testInfo) => {
- const home = mkdtempSync(join(tmpdir(), 'yaoyao-offline-ui-'))
- const { createApplication, createNodeServer } = await import(pathToFileURL(join(process.cwd(), 'dist-server/server/app.js')).href)
- const { SystemUpdateManager } = await import(pathToFileURL(join(process.cwd(), 'dist-server/server/updateManager.js')).href)
- const current = JSON.parse(readFileSync('release.json', 'utf8'))
- const [major, minor, patch] = current.webVersion.split('.').map(Number)
- const version = `${major}.${minor}.${patch + 1}`
- const latest = { ...current, releaseVersion: version, webVersion: version, gitTag: `v${version}` }
- const config = {
- host: '127.0.0.1', port: 0, upstream: new URL('http://127.0.0.1:1'),
- allowedHosts: new Set(['127.0.0.1']), home, mediaRoot: home, attachmentsRoot: home, imagesRoot: home,
- mediaOwner: 'test', allowInsecureLan: false, insecureLan: false, production: true,
- }
- const launched: string[] = []
- const updates = new SystemUpdateManager(config, {
- projectRoot: process.cwd(), platform: 'darwin',
- inspectRemote: async () => ({ manifest: latest, commit: 'b'.repeat(40) }),
- // Exercise scheduling and polling only; never install or stop a real service.
- launchUpdater: (path: string) => {
- const job = JSON.parse(readFileSync(path, 'utf8'))
- launched.push(job.target.releaseVersion)
- writeFileSync(path, JSON.stringify({ ...job, state: 'succeeded', message: '离线 Web 升级任务验收完成' }))
- rmSync(join(home, 'updates', 'active.lock'))
- },
- })
- const runtime = createApplication({ config, updates })
- runtime.app.use(serve(join(process.cwd(), 'dist')))
- runtime.app.use(async (ctx: Parameters<ReturnType<typeof serve>>[0]) => {
- if (ctx.method === 'GET' && ctx.accepts('html')) await send(ctx, 'index.html', { root: join(process.cwd(), 'dist') })
- })
- const node = createNodeServer(runtime)
- node.server.listen(0, '127.0.0.1'); await once(node.server, 'listening')
- const origin = `http://127.0.0.1:${(node.server.address() as AddressInfo).port}`
- try {
- const bootstrap = await (await page.request.get(origin + '/api/app/bootstrap')).json()
- const login = await page.request.post(origin + '/api/app/login', {
- headers: { Origin: origin, 'X-CSRF-Token': bootstrap.csrfToken }, data: { username: 'admin', password: 'admin' },
- })
- const signedIn = await login.json()
- expect(login.ok(), `${login.status()} ${signedIn.error || ''}`).toBe(true)
- const changed = await page.request.put(origin + '/api/app/account/credentials', {
- headers: { Origin: origin, 'X-CSRF-Token': signedIn.csrfToken },
- data: { currentPassword: 'admin', newPassword: 'offline-e2e-password' },
- })
- expect(changed.ok()).toBe(true)
- expect((await page.request.get(origin + '/readyz')).status()).toBe(503)
- await page.goto(origin + '/chat')
- await page.getByRole('button', { name: '打开设置中心' }).click()
- const dialog = page.getByRole('dialog', { name: '设置中心' })
- await dialog.getByRole('button', { name: '系统概览', exact: true }).click()
- await expect(dialog.getByText(`Web ${current.webVersion} · 可独立升级与回滚`)).toBeVisible()
- await dialog.getByRole('button', { name: '更新与回滚', exact: true }).click()
- await expect(dialog.getByText('未检测(不影响 Web 升级)')).toBeVisible()
- await expect(dialog.getByText(version, { exact: true })).toBeVisible()
- await expect(dialog.getByRole('alert')).toHaveCount(0)
- await expect(page.locator('.settings-center-layer')).toHaveCSS('opacity', '1')
- await page.screenshot({ path: testInfo.outputPath('offline-web-update.png') })
- page.once('dialog', confirmation => confirmation.accept())
- await dialog.getByRole('button', { name: '升级 Web', exact: true }).click()
- await expect(dialog.getByText('离线 Web 升级任务验收完成')).toBeVisible()
- expect(launched).toEqual([version])
- } finally {
- await page.goto('about:blank')
- node.server.closeAllConnections()
- await node.close()
- rmSync(home, { recursive: true, force: true })
- }
- })
|