summaryrefslogtreecommitdiffhomepage
path: root/packages/app/e2e/projects
diff options
context:
space:
mode:
authorLuke Parker <[email protected]>2026-03-20 14:12:06 +1000
committerGitHub <[email protected]>2026-03-20 00:12:06 -0400
commitd460614cd7ad9e047a2792139ea67e16caa82ea7 (patch)
treeff415e8719c7b6edd73bc824da379308e4e62589 /packages/app/e2e/projects
parent7866dbcfcc36a60d22ad466eddf54c54b21fabe3 (diff)
downloadopencode-d460614cd7ad9e047a2792139ea67e16caa82ea7.tar.gz
opencode-d460614cd7ad9e047a2792139ea67e16caa82ea7.zip
fix: lots of desktop stability, better e2e error logging (#18300)
Diffstat (limited to 'packages/app/e2e/projects')
-rw-r--r--packages/app/e2e/projects/projects-switch.spec.ts53
-rw-r--r--packages/app/e2e/projects/workspace-new-session.spec.ts71
2 files changed, 34 insertions, 90 deletions
diff --git a/packages/app/e2e/projects/projects-switch.spec.ts b/packages/app/e2e/projects/projects-switch.spec.ts
index e9cbf868d..b46c1b407 100644
--- a/packages/app/e2e/projects/projects-switch.spec.ts
+++ b/packages/app/e2e/projects/projects-switch.spec.ts
@@ -1,5 +1,4 @@
import { base64Decode } from "@opencode-ai/util/encode"
-import type { Page } from "@playwright/test"
import { test, expect } from "../fixtures"
import {
defocus,
@@ -7,43 +6,14 @@ import {
cleanupTestProject,
openSidebar,
sessionIDFromUrl,
- waitDir,
+ setWorkspacesEnabled,
+ waitSession,
+ waitSessionSaved,
waitSlug,
} from "../actions"
import { projectSwitchSelector, promptSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors"
import { dirSlug, resolveDirectory } from "../utils"
-async function workspaces(page: Page, directory: string, enabled: boolean) {
- await page.evaluate(
- ({ directory, enabled }: { directory: string; enabled: boolean }) => {
- const key = "opencode.global.dat:layout"
- const raw = localStorage.getItem(key)
- const data = raw ? JSON.parse(raw) : {}
- const sidebar = data.sidebar && typeof data.sidebar === "object" ? data.sidebar : {}
- const current =
- sidebar.workspaces && typeof sidebar.workspaces === "object" && !Array.isArray(sidebar.workspaces)
- ? sidebar.workspaces
- : {}
- const next = { ...current }
-
- if (enabled) next[directory] = true
- if (!enabled) delete next[directory]
-
- localStorage.setItem(
- key,
- JSON.stringify({
- ...data,
- sidebar: {
- ...sidebar,
- workspaces: next,
- },
- }),
- )
- },
- { directory, enabled },
- )
-}
-
test("can switch between projects from sidebar", async ({ page, withProject }) => {
await page.setViewportSize({ width: 1400, height: 800 })
@@ -84,9 +54,7 @@ test("switching back to a project opens the latest workspace session", async ({
await withProject(
async ({ directory, slug, trackSession, trackDirectory }) => {
await defocus(page)
- await workspaces(page, directory, true)
- await page.reload()
- await expect(page.locator(promptSelector)).toBeVisible()
+ await setWorkspacesEnabled(page, slug, true)
await openSidebar(page)
await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible()
@@ -108,8 +76,7 @@ test("switching back to a project opens the latest workspace session", async ({
await expect(btn).toBeVisible()
await btn.click({ force: true })
- await waitSlug(page)
- await waitDir(page, space)
+ await waitSession(page, { directory: space })
// Create a session by sending a prompt
const prompt = page.locator(promptSelector)
@@ -123,6 +90,7 @@ test("switching back to a project opens the latest workspace session", async ({
const created = sessionIDFromUrl(page.url())
if (!created) throw new Error(`Failed to get session ID from url: ${page.url()}`)
trackSession(created, space)
+ await waitSessionSaved(space, created)
await expect(page).toHaveURL(new RegExp(`/${next}/session/${created}(?:[/?#]|$)`))
@@ -130,15 +98,14 @@ test("switching back to a project opens the latest workspace session", async ({
const otherButton = page.locator(projectSwitchSelector(otherSlug)).first()
await expect(otherButton).toBeVisible()
- await otherButton.click()
- await expect(page).toHaveURL(new RegExp(`/${otherSlug}/session`))
+ await otherButton.click({ force: true })
+ await waitSession(page, { directory: other })
const rootButton = page.locator(projectSwitchSelector(slug)).first()
await expect(rootButton).toBeVisible()
- await rootButton.click()
+ await rootButton.click({ force: true })
- await waitDir(page, space)
- await expect.poll(() => sessionIDFromUrl(page.url()) ?? "").toBe(created)
+ await waitSession(page, { directory: space, sessionID: created })
await expect(page).toHaveURL(new RegExp(`/session/${created}(?:[/?#]|$)`))
},
{ extra: [other] },
diff --git a/packages/app/e2e/projects/workspace-new-session.spec.ts b/packages/app/e2e/projects/workspace-new-session.spec.ts
index 0858f2627..3a7a6bbc2 100644
--- a/packages/app/e2e/projects/workspace-new-session.spec.ts
+++ b/packages/app/e2e/projects/workspace-new-session.spec.ts
@@ -1,6 +1,15 @@
import type { Page } from "@playwright/test"
import { test, expect } from "../fixtures"
-import { openSidebar, resolveSlug, sessionIDFromUrl, setWorkspacesEnabled, waitDir, waitSlug } from "../actions"
+import {
+ openSidebar,
+ resolveSlug,
+ sessionIDFromUrl,
+ setWorkspacesEnabled,
+ waitDir,
+ waitSession,
+ waitSessionSaved,
+ waitSlug,
+} from "../actions"
import { promptSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors"
import { createSdk } from "../utils"
@@ -14,20 +23,7 @@ function button(space: { slug: string; raw: string }) {
async function waitWorkspaceReady(page: Page, space: { slug: string; raw: string }) {
await openSidebar(page)
- await expect
- .poll(
- async () => {
- const row = page.locator(item(space)).first()
- try {
- await row.hover({ timeout: 500 })
- return true
- } catch {
- return false
- }
- },
- { timeout: 60_000 },
- )
- .toBe(true)
+ await expect(page.locator(item(space)).first()).toBeVisible({ timeout: 60_000 })
}
async function createWorkspace(page: Page, root: string, seen: string[]) {
@@ -49,7 +45,8 @@ async function openWorkspaceNewSession(page: Page, space: { slug: string; raw: s
await expect(next).toBeVisible()
await next.click({ force: true })
- return waitDir(page, space.directory)
+ await waitSession(page, { directory: space.directory })
+ await expect.poll(() => sessionIDFromUrl(page.url()) ?? "").toBe("")
}
async function createSessionFromWorkspace(
@@ -57,39 +54,28 @@ async function createSessionFromWorkspace(
space: { slug: string; raw: string; directory: string },
text: string,
) {
- const next = await openWorkspaceNewSession(page, space)
+ await openWorkspaceNewSession(page, space)
const prompt = page.locator(promptSelector)
await expect(prompt).toBeVisible()
- await expect(prompt).toBeEditable()
- await prompt.click()
- await expect(prompt).toBeFocused()
await prompt.fill(text)
- await expect.poll(async () => ((await prompt.textContent()) ?? "").trim()).toContain(text)
- await prompt.press("Enter")
-
- await waitDir(page, next.directory)
- await expect.poll(() => sessionIDFromUrl(page.url()) ?? "", { timeout: 30_000 }).not.toBe("")
+ await page.keyboard.press("Enter")
+ await expect.poll(() => sessionIDFromUrl(page.url()) ?? "", { timeout: 15_000 }).not.toBe("")
const sessionID = sessionIDFromUrl(page.url())
if (!sessionID) throw new Error(`Failed to parse session id from url: ${page.url()}`)
- await expect(page).toHaveURL(new RegExp(`/session/${sessionID}(?:[/?#]|$)`))
- return { sessionID, slug: next.slug }
-}
-async function sessionDirectory(directory: string, sessionID: string) {
- const info = await createSdk(directory)
- .session.get({ sessionID })
- .then((x) => x.data)
+ await waitSessionSaved(space.directory, sessionID)
+ await createSdk(space.directory)
+ .session.abort({ sessionID })
.catch(() => undefined)
- if (!info) return ""
- return info.directory
+ return sessionID
}
test("new sessions from sidebar workspace actions stay in selected workspace", async ({ page, withProject }) => {
await page.setViewportSize({ width: 1400, height: 800 })
- await withProject(async ({ directory, slug: root, trackSession, trackDirectory }) => {
+ await withProject(async ({ slug: root, trackDirectory, trackSession }) => {
await openSidebar(page)
await setWorkspacesEnabled(page, root, true)
@@ -101,17 +87,8 @@ test("new sessions from sidebar workspace actions stay in selected workspace", a
trackDirectory(second.directory)
await waitWorkspaceReady(page, second)
- const firstSession = await createSessionFromWorkspace(page, first.slug, `workspace one ${Date.now()}`)
- trackSession(firstSession.sessionID, first.directory)
-
- const secondSession = await createSessionFromWorkspace(page, second.slug, `workspace two ${Date.now()}`)
- trackSession(secondSession.sessionID, second.directory)
-
- const thirdSession = await createSessionFromWorkspace(page, first.slug, `workspace one again ${Date.now()}`)
- trackSession(thirdSession.sessionID, first.directory)
-
- await expect.poll(() => sessionDirectory(first.directory, firstSession.sessionID)).toBe(first.directory)
- await expect.poll(() => sessionDirectory(second.directory, secondSession.sessionID)).toBe(second.directory)
- await expect.poll(() => sessionDirectory(first.directory, thirdSession.sessionID)).toBe(first.directory)
+ trackSession(await createSessionFromWorkspace(page, first, `workspace one ${Date.now()}`), first.directory)
+ trackSession(await createSessionFromWorkspace(page, second, `workspace two ${Date.now()}`), second.directory)
+ trackSession(await createSessionFromWorkspace(page, first, `workspace one again ${Date.now()}`), first.directory)
})
})