Procházet zdrojové kódy

补齐持久登录后的桌面升级验收并说明安卓推送配置

Samien před 1 měsícem
rodič
revize
126c37e71c

+ 4 - 7
desktop/service-sync.test.mjs

@@ -88,13 +88,10 @@ test('App first launch installs an independent Web; Web remains up after quit an
       assert.equal(marker.action, 'upgrade')
       assert.equal(driver.snapshot().plist.EnvironmentVariables.YAOYAO_TEST_PRESERVE, 'historical-release-settings')
     }
-    const support = await page.evaluate(async () => {
-      const bootstrap = await (await fetch('/api/app/bootstrap')).json()
-      const setup = await fetch('/api/app/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': bootstrap.csrfToken },
-        body: JSON.stringify({ username: 'sync-fixture', password: 'sync-fixture-password' }) })
-      if (!setup.ok) throw new Error('验收账号创建失败')
-      return (await fetch('/api/app/system/update/status')).json()
-    })
+    // Credential setup can overlap the SPA's first route navigation; retry only this read.
+    const support = await until(() => page.evaluate(async () =>
+      (await fetch('/api/app/system/update/status')).json()), value => value.installationMode === 'release')
+
     assert.equal(support.installationMode, 'release'); assert.equal(support.supported, true)
     await nativeQuit(app); app = undefined
     assert.equal((await localRequest(`http://127.0.0.1:${port}/healthz`)).body.ok, true)

+ 4 - 0
desktop/update-entry.test.mjs

@@ -16,6 +16,8 @@ test('the main local app can open the native updater and repeated requests reuse
   let releaseIdentity
   const identityReady = new Promise(resolve => { releaseIdentity = resolve })
   const server = createServer(async (req, res) => {
+    if (req.url === '/desktop/service/session') { res.setHeader('Content-Type','application/json'); res.end(JSON.stringify({user:{role:'admin',localDesktop:true},setCookies:['hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000']})); return }
+    if (req.url === '/api/app/desktop-session') { res.setHeader('Set-Cookie','hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000'); res.end('{}'); return }
     if (req.url === '/desktop/service') { await identityReady; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(identity)) }
     else if(req.url.split('?')[0]==='/api/app/bootstrap'){res.setHeader('Content-Type','application/json');res.end(JSON.stringify({authenticated:true,csrfToken:'fixture'}))}
     else { res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.end('<title>Update entry fixture</title><button onclick="window.yaoyaoDesktop.openUpdates()">检测更新</button>') }
@@ -57,6 +59,8 @@ test('client mode opens local App updates without a local service or admin role'
   const root = resolve(import.meta.dirname, '..')
   const home = await realpath(await mkdtemp(join(tmpdir(), 'yaoyao-client-update-')))
   const remote = createServer((req, res) => {
+    if (req.url === '/desktop/service/session') { res.setHeader('Content-Type','application/json'); res.end(JSON.stringify({user:{role:'admin',localDesktop:true},setCookies:['hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000']})); return }
+    if (req.url === '/api/app/desktop-session') { res.setHeader('Set-Cookie','hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000'); res.end('{}'); return }
     if (req.url.split('?')[0] === '/api/app/bootstrap') { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ authenticated: true, csrfToken: 'fixture', user: { role: 'member' } })) }
     else { res.setHeader('Content-Type', 'text/html'); res.end('<title>Remote member</title><button onclick="window.yaoyaoDesktop.openUpdates()">App update</button>') }
   })

+ 4 - 2
desktop/update-restart.test.mjs

@@ -7,14 +7,16 @@ import { createServer } from 'node:http'
 import { _electron as electron, expect } from '@playwright/test'
 import { dataKey } from './service-manager.mjs'
 
-for (const scenario of ['remote', 'local', 'remote-failure', 'local-failure', 'local-checking-failure']) test(`${scenario} restart releases the lock, preserves independent servers and recovers on failure`, { timeout: 60000 }, async () => {
-  const mode = scenario.startsWith('local') ? 'local' : 'remote', fail = scenario.endsWith('failure'), checking = scenario === 'local-checking-failure'
+for (const scenario of ['remote', 'local', 'remote-failure', 'local-failure', 'remote-checking-failure']) test(`${scenario} restart releases the lock, preserves independent servers and recovers on failure`, { timeout: 60000 }, async () => {
+  const mode = scenario.startsWith('local') ? 'local' : 'remote', fail = scenario.endsWith('failure'), checking = scenario === 'remote-checking-failure'
   const root = resolve(import.meta.dirname, '..'), home = await realpath(await mkdtemp(join(tmpdir(), 'yaoyao-update-restart-')))
   const version = JSON.parse(await readFile(join(root, 'release.json'), 'utf8')).webVersion
   const identity = { protocol: 1, instanceId: 'update-restart', pid: process.pid, dataKey: dataKey(home), version }
   let activationRequired = true, activations = 0, inspections = 0
   let releaseIdentity; const identityReady = new Promise(resolve => { releaseIdentity = resolve })
   const server = createServer(async (req, res) => {
+    if (req.url === '/desktop/service/session') { res.setHeader('Content-Type','application/json'); res.end(JSON.stringify({user:{role:'admin',localDesktop:true},setCookies:['hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000']})); return }
+    if (req.url === '/api/app/desktop-session') { res.setHeader('Set-Cookie','hermes_yaoyao_session=fixture; Path=/; HttpOnly; Max-Age=31536000'); res.end('{}'); return }
     res.setHeader('Content-Type', 'application/json')
     if (req.url === '/desktop/service') { await identityReady; inspections++; res.end(JSON.stringify({ ...identity, activationRequired })) }
     else if (req.url === '/desktop/service/activate') { assert.equal(req.method, 'POST'); assert.equal(req.headers['x-yaoyao-desktop-token'], 'fixture'); if (activationRequired) activations++; activationRequired = false; res.end(JSON.stringify({ activated: true })) }

+ 1 - 0
docs/releases/v0.4.75.md

@@ -18,6 +18,7 @@
 - macOS 桌面使用 Developer ID Application 正式分发签名及 Apple 公证,提供完整自动更新附件;已安装正式签名版的用户可使用“下载更新 → 重启更新”,历史开发签名版请先手动安装正式 DMG。
 - Windows 为未签名测试客户端,可能提示未知发布者;安装到当前用户目录,连接已有服务器,不托管本机服务。
 - Windows 测试更新清单随独立元数据压缩包提供,不写入正式自动更新源。Windows Server CI 验证结果与尚未完成的 Windows 10/11 真机项目分别列出,详见 [客户端说明](https://github.com/Lsamien/yaoyao/blob/v0.4.75/docs/windows-client.md)。
+- Android APK 暂未内置 Firebase 配置,系统远程推送尚未配置;应用内消息与未读同步仍可使用。
 - Android APK 为 1.5.0(226),沿用正式发布签名。安装前建议备份数据;旧版本标签和附件继续保留。
 - 主项目采用 Apache-2.0,第三方组件保留各自许可与署名。