Ver Fonte

修正桌面 E2E 凭据夹具并覆盖双构建源码入口

Samien há 1 mês atrás
pai
commit
050ccf085c
2 ficheiros alterados com 48 adições e 18 exclusões
  1. 31 0
      desktop/source-entry.test.mjs
  2. 17 18
      desktop/test-support/onboarding.mjs

+ 31 - 0
desktop/source-entry.test.mjs

@@ -0,0 +1,31 @@
+import { test } from 'node:test'
+import assert from 'node:assert/strict'
+import { mkdtemp, rm } from 'node:fs/promises'
+import { tmpdir } from 'node:os'
+import { join, resolve } from 'node:path'
+import { _electron as electron } from '@playwright/test'
+
+const root = resolve(import.meta.dirname, '..')
+// Both staged variants coexist after packaging. The source entry must use the
+// requested variant's manifest and policy without moving either build marker.
+for (const clientOnly of [false, true]) {
+  test(`source entry selects the ${clientOnly ? 'client' : 'full'} staged variant`, { timeout: 45000 }, async () => {
+    const home = await mkdtemp(join(tmpdir(), 'yaoyao-source-entry-'))
+    let app
+    try {
+      app = await electron.launch({ args: [root], cwd: root, env: { ...process.env,
+        HERMES_YAOYAO_DESKTOP_TEST_HOME: home, HERMES_YAOYAO_DESKTOP_TEST_MODE: 'ask',
+        HERMES_YAOYAO_DESKTOP_CLIENT_ONLY: clientOnly ? '1' : '0', HERMES_YAOYAO_DESKTOP_PORT: '1',
+        HERMES_YAOYAO_DESKTOP_TEST_SYNC: '0' }, timeout: 30000 })
+      const page = await app.firstWindow()
+      await page.waitForURL(/boot\.html$/)
+      assert.equal(await app.evaluate(({ app }) => app.getName()), clientOnly ? '夭夭' : '夭夭完整版')
+      const state = await page.evaluate(() => window.yaoyaoDesktop.status())
+      assert.deepEqual(state.supportedModes, !clientOnly && process.platform === 'darwin' ? ['client', 'server'] : ['client'])
+      assert.equal(state.mode, !clientOnly && process.platform === 'darwin' ? null : 'remote')
+    } finally {
+      await app?.close().catch(() => {})
+      await rm(home, { recursive: true, force: true })
+    }
+  })
+}

+ 17 - 18
desktop/test-support/onboarding.mjs

@@ -1,22 +1,21 @@
 /** Enter through the native local-admin flow, then set isolated fixture credentials. */
 /** Enter through the native local-admin flow, then set isolated fixture credentials. */
 export async function enterLocal(page, { username = 'desktop-fixture', password = 'desktop-fixture-password' } = {}) {
 export async function enterLocal(page, { username = 'desktop-fixture', password = 'desktop-fixture-password' } = {}) {
   await page.waitForURL(url => url.protocol === 'http:' || url.protocol === 'https:', { timeout: 90000 })
   await page.waitForURL(url => url.protocol === 'http:' || url.protocol === 'https:', { timeout: 90000 })
-  await page.evaluate(async ({username,password}) => {
-    const bootstrap = await (await fetch('/api/app/bootstrap')).json()
-    if (!bootstrap.user?.localDesktop) throw new Error('Native administrator session was not established')
-    const response = await fetch('/api/app/account/credentials', { method: 'PUT',
-      headers: {'Content-Type':'application/json','X-CSRF-Token':bootstrap.csrfToken},
-      body: JSON.stringify({username,currentPassword:'',newPassword:password}) })
-    if (!response.ok) throw new Error('Fixture account configuration failed')
-  }, {username,password})
-  // The native service may finish its own navigation after credentials rotate.
-  // Retry only interrupted navigation; all other browser failures remain errors.
-  const url = new URL('/conversations', page.url()).href
-  for (let attempt = 0; ; attempt++) {
-    try { await page.goto(url); break }
-    catch (error) {
-      if (attempt >= 2 || !String(error.message).includes('net::ERR_ABORTED')) throw error
-      await page.waitForLoadState('load')
-    }
-  }
+  // Rotate fixture credentials outside the SPA: its in-flight requests still
+  // carry the previous session and can otherwise trigger native login recovery.
+  const origin = new URL(page.url()).origin
+  const fixtureURL = `${origin}/__desktop_fixture_credentials__`
+  await page.route(fixtureURL, route => route.fulfill({ contentType: 'text/html', body: '<title>Fixture account setup</title>' }))
+  try {
+    await page.goto(fixtureURL)
+    await page.evaluate(async ({username,password}) => {
+      const bootstrap = await (await fetch('/api/app/bootstrap')).json()
+      if (!bootstrap.user?.localDesktop) throw new Error('Native administrator session was not established')
+      const response = await fetch('/api/app/account/credentials', { method: 'PUT',
+        headers: {'Content-Type':'application/json','X-CSRF-Token':bootstrap.csrfToken},
+        body: JSON.stringify({username,currentPassword:'',newPassword:password}) })
+      if (!response.ok) throw new Error('Fixture account configuration failed')
+    }, {username,password})
+  } finally { await page.unroute(fixtureURL) }
+  await page.goto(`${origin}/conversations`)
 }
 }