fix(e2e): launch plugins with real app identity (#11024)

This commit is contained in:
Neil
2026-07-27 17:56:07 -07:00
committed by GitHub
parent 9c5d827d6a
commit bd5a991ce7
5 changed files with 50 additions and 31 deletions
+6 -2
View File
@@ -1,6 +1,10 @@
import { dirname } from 'node:path'
export function getOrcaElectronLaunchArgs(mainPath: string, headful: boolean): string[] {
// Launch through package.json so app version and resource paths match a packaged app.
const appPath = dirname(dirname(dirname(mainPath)))
if (headful || process.platform !== 'linux') {
return [mainPath]
return [appPath]
}
// Why: Ubuntu CI cannot run Electron's setuid chrome-sandbox (not root-owned
@@ -16,6 +20,6 @@ export function getOrcaElectronLaunchArgs(mainPath: string, headful: boolean): s
'--disable-gpu-sandbox',
'--disable-dev-shm-usage',
'--in-process-gpu',
mainPath
appPath
]
}
@@ -0,0 +1,13 @@
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
import { getOrcaElectronLaunchArgs } from './electron-launch-args'
describe('getOrcaElectronLaunchArgs', () => {
it('launches the package root that owns the compiled main entry', () => {
const root = join('workspace', 'orca')
const mainPath = join(root, 'out', 'main', 'index.js')
expect(getOrcaElectronLaunchArgs(mainPath, true)).toEqual([root])
expect(getOrcaElectronLaunchArgs(mainPath, false).at(-1)).toBe(root)
})
})
+3 -2
View File
@@ -107,12 +107,13 @@ test('runs hello-orca panel, command, and event behind visible consent', async (
expect(installed.blocked).toBe(true)
await openPluginSettings(orcaPage)
await orcaPage.getByRole('tab', { name: /^Installed/ }).click()
const row = orcaPage.locator(`[data-plugin-key="${installed.pluginKey}"]`)
await expect(row).toContainText('Needs review')
await row.getByRole('button', { name: 'Review permissions' }).click()
await row.getByRole('button', { name: 'Review & enable' }).click()
const consent = orcaPage.getByRole('dialog', { name: 'Review permissions' })
await expect(consent).toBeVisible()
await expect(consent).toContainText(pluginRoot)
await expect(consent).toContainText('Local folder')
await expect(consent).toContainText('full access to your files, network, and other processes')
await expect(consent.getByRole('button', { name: 'Keep Disabled' })).toBeFocused()
await consent.getByRole('button', { name: 'Enable plugin' }).click()
+21 -17
View File
@@ -76,16 +76,10 @@ async function copyLaunchPlugin(
async function configureFixtureGit(home: string, repositories: string): Promise<NodeJS.ProcessEnv> {
const hooksDirectory = join(home, 'hooks')
const xdgConfigHome = join(home, 'xdg')
const configPath = join(home, '.gitconfig')
await Promise.all([
mkdir(hooksDirectory, { recursive: true }),
mkdir(xdgConfigHome, { recursive: true })
])
await mkdir(hooksDirectory, { recursive: true })
const gitEnvironment: NodeJS.ProcessEnv = {
HOME: home,
USERPROFILE: home,
XDG_CONFIG_HOME: xdgConfigHome,
GIT_CONFIG_GLOBAL: configPath,
GIT_CONFIG_NOSYSTEM: '1',
GIT_TERMINAL_PROMPT: '0'
}
@@ -184,9 +178,9 @@ async function installMarketplacePluginThroughUi(
): Promise<void> {
const listing = page.locator(`[data-marketplace-plugin-key="${pluginKey}"]`)
await expect(listing).toBeVisible()
await listing.getByRole('button', { name: 'Review' }).click()
await listing.getByRole('button', { name: 'Install' }).click()
const preview = page.getByRole('dialog', { name: pluginName })
await expect(preview).toContainText(pluginKey)
await expect(preview).toContainText('Official · stablyai')
await preview.getByRole('button', { name: 'Install plugin' }).click()
const consent = page.getByRole('dialog', { name: consentDialogName })
await expect(consent).toBeVisible()
@@ -194,6 +188,21 @@ async function installMarketplacePluginThroughUi(
await expect(consent).toBeHidden()
}
async function enableInstalledPluginThroughUi(
page: Page,
pluginKey: string,
consentDialogName: string
): Promise<void> {
await page.getByRole('tab', { name: /^Installed/ }).click()
const plugin = page.locator(`[data-plugin-key="${pluginKey}"]`)
await expect(plugin).toBeVisible()
await plugin.getByRole('button', { name: 'Review & enable' }).click()
const consent = page.getByRole('dialog', { name: consentDialogName })
await expect(consent).toBeVisible()
await consent.getByRole('button', { name: 'Enable plugin' }).click()
await expect(consent).toBeHidden()
}
async function applyInstalledLanguage(page: Page): Promise<void> {
const languageId = 'plugin:stablyai.orca-portuguese/pt-BR'
await page.evaluate(() => {
@@ -251,10 +260,9 @@ async function runMarketplaceJourney(page: Page): Promise<void> {
'Multipass VM Recipes',
'Review plugin content'
)
await installMarketplacePluginThroughUi(
await enableInstalledPluginThroughUi(
page,
'stablyai.orca-navigation-shortcuts',
'Orca Navigation Shortcuts',
'Review plugin content'
)
@@ -266,11 +274,7 @@ async function runMarketplaceJourney(page: Page): Promise<void> {
test('installs and applies official Phase 1 content from a fresh profile', async ({}, testInfo) => {
test.setTimeout(180_000)
const fixture = await createMarketplaceFixture()
const session = createRestartSession(testInfo as TestInfo, {
extraEnv: {
...fixture.gitEnvironment
}
})
const session = createRestartSession(testInfo as TestInfo, fixture.gitEnvironment)
let launched: Awaited<ReturnType<typeof session.launch>> | null = null
try {
launched = await session.launch()
+7 -10
View File
@@ -6,7 +6,7 @@
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import { expect, test, type ElectronApplication, type TestInfo } from '@stablyai/playwright-test'
import { expect, test, type TestInfo } from '@stablyai/playwright-test'
import { fingerprintPluginConsent } from '../../src/shared/plugins/plugin-consent-fingerprint'
import { pluginManifestSchema } from '../../src/shared/plugins/plugin-manifest'
import { createRestartSession } from './helpers/orca-restart'
@@ -84,12 +84,11 @@ async function launchSample(
testInfo: TestInfo
): Promise<StartupSample> {
let output = ''
const attachLogs = (app: ElectronApplication): void => {
app.process().stderr?.on('data', (chunk: Buffer) => {
output += chunk.toString('utf8')
})
}
const launched = await session.launch(attachLogs)
const launched = await session.launch({
onStderr: (chunk) => {
output += chunk
}
})
try {
await expect
.poll(
@@ -127,9 +126,7 @@ function median(values: readonly number[]): number {
// oxlint-disable-next-line no-empty-pattern -- Playwright passes fixtures before testInfo.
test('keeps real Electron launch stable with 20 approved inert plugins', async ({}, testInfo) => {
test.setTimeout(240_000)
const session = createRestartSession(testInfo, {
extraEnv: { ORCA_STARTUP_DIAGNOSTICS: '1' }
})
const session = createRestartSession(testInfo, { ORCA_STARTUP_DIAGNOSTICS: '1' })
const baseline: StartupSample[] = []
const populated: StartupSample[] = []
let markerPaths: string[] = []