summaryrefslogtreecommitdiffhomepage
path: root/packages/app/e2e/projects
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2026-04-14 23:10:07 -0400
committerDax Raad <[email protected]>2026-04-14 23:10:25 -0400
commit627159acac04409d7697a6739e2c572c2a010943 (patch)
tree5f87465ea69f41aff0cd96ae5411fe438da480b3 /packages/app/e2e/projects
parentf44aa02e2677b2b89a1a9f517c0ff8990383deaa (diff)
downloadopencode-627159acac04409d7697a6739e2c572c2a010943.tar.gz
opencode-627159acac04409d7697a6739e2c572c2a010943.zip
delete all e2e tests (#22501)
Cherry-picked from ea463e604cdd2a3e83e1c286e39b789455f0d413
Diffstat (limited to 'packages/app/e2e/projects')
-rw-r--r--packages/app/e2e/projects/project-edit.spec.ts49
-rw-r--r--packages/app/e2e/projects/projects-close.spec.ts49
-rw-r--r--packages/app/e2e/projects/projects-switch.spec.ts94
-rw-r--r--packages/app/e2e/projects/workspace-new-session.spec.ts78
-rw-r--r--packages/app/e2e/projects/workspaces.spec.ts368
5 files changed, 0 insertions, 638 deletions
diff --git a/packages/app/e2e/projects/project-edit.spec.ts b/packages/app/e2e/projects/project-edit.spec.ts
deleted file mode 100644
index 1ffe4219d..000000000
--- a/packages/app/e2e/projects/project-edit.spec.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { test, expect } from "../fixtures"
-import { clickMenuItem, openProjectMenu, openSidebar } from "../actions"
-
-test("dialog edit project updates name and startup script", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- await project.open()
- await openSidebar(page)
-
- const open = async () => {
- const menu = await openProjectMenu(page, project.slug)
- await clickMenuItem(menu, /^Edit$/i, { force: true })
-
- const dialog = page.getByRole("dialog")
- await expect(dialog).toBeVisible()
- await expect(dialog.getByRole("heading", { level: 2 })).toHaveText("Edit project")
- return dialog
- }
-
- const name = `e2e project ${Date.now()}`
- const startup = `echo e2e_${Date.now()}`
-
- const dialog = await open()
-
- const nameInput = dialog.getByLabel("Name")
- await nameInput.fill(name)
-
- const startupInput = dialog.getByLabel("Workspace startup script")
- await startupInput.fill(startup)
-
- await dialog.getByRole("button", { name: "Save" }).click()
- await expect(dialog).toHaveCount(0)
-
- await expect
- .poll(
- async () => {
- await page.reload()
- await openSidebar(page)
- const reopened = await open()
- const value = await reopened.getByLabel("Name").inputValue()
- const next = await reopened.getByLabel("Workspace startup script").inputValue()
- await reopened.getByRole("button", { name: "Cancel" }).click()
- await expect(reopened).toHaveCount(0)
- return `${value}\n${next}`
- },
- { timeout: 30_000 },
- )
- .toBe(`${name}\n${startup}`)
-})
diff --git a/packages/app/e2e/projects/projects-close.spec.ts b/packages/app/e2e/projects/projects-close.spec.ts
deleted file mode 100644
index 75e6f2ce6..000000000
--- a/packages/app/e2e/projects/projects-close.spec.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { test, expect } from "../fixtures"
-import { createTestProject, cleanupTestProject, openSidebar, clickMenuItem, openProjectMenu } from "../actions"
-import { projectSwitchSelector } from "../selectors"
-import { dirSlug } from "../utils"
-
-test("closing active project navigates to another open project", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- const other = await createTestProject()
- const otherSlug = dirSlug(other)
-
- try {
- await project.open({ extra: [other] })
- await openSidebar(page)
-
- const otherButton = page.locator(projectSwitchSelector(otherSlug)).first()
- await expect(otherButton).toBeVisible()
- await otherButton.click()
-
- await expect(page).toHaveURL(new RegExp(`/${otherSlug}/session`))
-
- const menu = await openProjectMenu(page, otherSlug)
- await clickMenuItem(menu, /^Close$/i, { force: true })
-
- await expect
- .poll(
- () => {
- const pathname = new URL(page.url()).pathname
- if (new RegExp(`^/${project.slug}/session(?:/[^/]+)?/?$`).test(pathname)) return "project"
- if (pathname === "/") return "home"
- return ""
- },
- { timeout: 15_000 },
- )
- .toMatch(/^(project|home)$/)
-
- await expect(page).not.toHaveURL(new RegExp(`/${otherSlug}/session(?:[/?#]|$)`))
- await expect
- .poll(
- async () => {
- return await page.locator(projectSwitchSelector(otherSlug)).count()
- },
- { timeout: 15_000 },
- )
- .toBe(0)
- } finally {
- await cleanupTestProject(other)
- }
-})
diff --git a/packages/app/e2e/projects/projects-switch.spec.ts b/packages/app/e2e/projects/projects-switch.spec.ts
deleted file mode 100644
index 67d09afd1..000000000
--- a/packages/app/e2e/projects/projects-switch.spec.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { base64Decode } from "@opencode-ai/util/encode"
-import { test, expect } from "../fixtures"
-import {
- defocus,
- createTestProject,
- cleanupTestProject,
- openSidebar,
- setWorkspacesEnabled,
- waitSession,
- waitSlug,
-} from "../actions"
-import { projectSwitchSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors"
-import { dirSlug, resolveDirectory } from "../utils"
-
-test("can switch between projects from sidebar", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- const other = await createTestProject()
- const otherSlug = dirSlug(other)
-
- try {
- await project.open({ extra: [other] })
- await defocus(page)
-
- const currentSlug = dirSlug(project.directory)
- const otherButton = page.locator(projectSwitchSelector(otherSlug)).first()
- await expect(otherButton).toBeVisible()
- await otherButton.click()
-
- await expect(page).toHaveURL(new RegExp(`/${otherSlug}/session`))
-
- const currentButton = page.locator(projectSwitchSelector(currentSlug)).first()
- await expect(currentButton).toBeVisible()
- await currentButton.click()
-
- await expect(page).toHaveURL(new RegExp(`/${currentSlug}/session`))
- } finally {
- await cleanupTestProject(other)
- }
-})
-
-test("switching back to a project opens the latest workspace session", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- const other = await createTestProject()
- const otherSlug = dirSlug(other)
- try {
- await project.open({ extra: [other] })
- await defocus(page)
- await setWorkspacesEnabled(page, project.slug, true)
- await openSidebar(page)
- await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible()
-
- await page.getByRole("button", { name: "New workspace" }).first().click()
-
- const raw = await waitSlug(page, [project.slug])
- const dir = base64Decode(raw)
- if (!dir) throw new Error(`Failed to decode workspace slug: ${raw}`)
- const space = await resolveDirectory(dir)
- const next = dirSlug(space)
- project.trackDirectory(space)
- await openSidebar(page)
-
- const item = page.locator(`${workspaceItemSelector(next)}, ${workspaceItemSelector(raw)}`).first()
- await expect(item).toBeVisible()
- await item.hover()
-
- const btn = page.locator(`${workspaceNewSessionSelector(next)}, ${workspaceNewSessionSelector(raw)}`).first()
- await expect(btn).toBeVisible()
- await btn.click({ force: true })
-
- await waitSession(page, { directory: space })
-
- const created = await project.user("test")
-
- await expect(page).toHaveURL(new RegExp(`/${next}/session/${created}(?:[/?#]|$)`))
-
- await openSidebar(page)
-
- const otherButton = page.locator(projectSwitchSelector(otherSlug)).first()
- await expect(otherButton).toBeVisible()
- await otherButton.click({ force: true })
- await waitSession(page, { directory: other })
-
- const rootButton = page.locator(projectSwitchSelector(project.slug)).first()
- await expect(rootButton).toBeVisible()
- await rootButton.click({ force: true })
-
- await waitSession(page, { directory: space, sessionID: created })
- await expect(page).toHaveURL(new RegExp(`/session/${created}(?:[/?#]|$)`))
- } finally {
- await cleanupTestProject(other)
- }
-})
diff --git a/packages/app/e2e/projects/workspace-new-session.spec.ts b/packages/app/e2e/projects/workspace-new-session.spec.ts
deleted file mode 100644
index d9d010b4d..000000000
--- a/packages/app/e2e/projects/workspace-new-session.spec.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import type { Page } from "@playwright/test"
-import { test, expect } from "../fixtures"
-import {
- openSidebar,
- resolveSlug,
- sessionIDFromUrl,
- setWorkspacesEnabled,
- waitDir,
- waitSession,
- waitSlug,
-} from "../actions"
-import { workspaceItemSelector, workspaceNewSessionSelector } from "../selectors"
-
-function item(space: { slug: string; raw: string }) {
- return `${workspaceItemSelector(space.slug)}, ${workspaceItemSelector(space.raw)}`
-}
-
-function button(space: { slug: string; raw: string }) {
- return `${workspaceNewSessionSelector(space.slug)}, ${workspaceNewSessionSelector(space.raw)}`
-}
-
-async function waitWorkspaceReady(page: Page, space: { slug: string; raw: string }) {
- await openSidebar(page)
- await expect(page.locator(item(space)).first()).toBeVisible({ timeout: 60_000 })
-}
-
-async function createWorkspace(page: Page, root: string, seen: string[]) {
- await openSidebar(page)
- await page.getByRole("button", { name: "New workspace" }).first().click()
-
- const next = await resolveSlug(await waitSlug(page, [root, ...seen]))
- await waitDir(page, next.directory)
- return next
-}
-
-async function openWorkspaceNewSession(page: Page, space: { slug: string; raw: string; directory: string }) {
- await waitWorkspaceReady(page, space)
-
- const row = page.locator(item(space)).first()
- await row.hover()
-
- const next = page.locator(button(space)).first()
- await expect(next).toBeVisible()
- await next.click({ force: true })
-
- await waitSession(page, { directory: space.directory })
- await expect.poll(() => sessionIDFromUrl(page.url()) ?? "").toBe("")
-}
-
-async function createSessionFromWorkspace(
- project: Parameters<typeof test>[0]["project"],
- page: Page,
- space: { slug: string; raw: string; directory: string },
- text: string,
-) {
- await openWorkspaceNewSession(page, space)
- return project.user(text)
-}
-
-test("new sessions from sidebar workspace actions stay in selected workspace", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- await project.open()
- await openSidebar(page)
- await setWorkspacesEnabled(page, project.slug, true)
-
- const first = await createWorkspace(page, project.slug, [])
- project.trackDirectory(first.directory)
- await waitWorkspaceReady(page, first)
-
- const second = await createWorkspace(page, project.slug, [first.slug])
- project.trackDirectory(second.directory)
- await waitWorkspaceReady(page, second)
-
- await createSessionFromWorkspace(project, page, first, `workspace one ${Date.now()}`)
- await createSessionFromWorkspace(project, page, second, `workspace two ${Date.now()}`)
- await createSessionFromWorkspace(project, page, first, `workspace one again ${Date.now()}`)
-})
diff --git a/packages/app/e2e/projects/workspaces.spec.ts b/packages/app/e2e/projects/workspaces.spec.ts
deleted file mode 100644
index 206baa47c..000000000
--- a/packages/app/e2e/projects/workspaces.spec.ts
+++ /dev/null
@@ -1,368 +0,0 @@
-import fs from "node:fs/promises"
-import os from "node:os"
-import path from "node:path"
-import { base64Decode } from "@opencode-ai/util/encode"
-import type { Page } from "@playwright/test"
-
-import { test, expect } from "../fixtures"
-
-test.describe.configure({ mode: "serial" })
-import {
- cleanupTestProject,
- clickMenuItem,
- confirmDialog,
- openSidebar,
- openWorkspaceMenu,
- resolveSlug,
- setWorkspacesEnabled,
- slugFromUrl,
- waitDir,
- waitSlug,
-} from "../actions"
-import { inlineInputSelector, workspaceItemSelector } from "../selectors"
-import { dirSlug } from "../utils"
-
-async function setupWorkspaceTest(page: Page, project: { slug: string; trackDirectory: (directory: string) => void }) {
- const rootSlug = project.slug
- await openSidebar(page)
-
- await setWorkspacesEnabled(page, rootSlug, true)
-
- await page.getByRole("button", { name: "New workspace" }).first().click()
- const next = await resolveSlug(await waitSlug(page, [rootSlug]))
- await waitDir(page, next.directory)
- project.trackDirectory(next.directory)
-
- await openSidebar(page)
-
- await expect
- .poll(
- async () => {
- const item = page.locator(workspaceItemSelector(next.slug)).first()
- try {
- await item.hover({ timeout: 500 })
- return true
- } catch {
- return false
- }
- },
- { timeout: 60_000 },
- )
- .toBe(true)
-
- return { rootSlug, slug: next.slug, directory: next.directory }
-}
-
-test("can enable and disable workspaces from project menu", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
-
- await openSidebar(page)
-
- await expect(page.getByRole("button", { name: "New session" }).first()).toBeVisible()
- await expect(page.getByRole("button", { name: "New workspace" })).toHaveCount(0)
-
- await setWorkspacesEnabled(page, project.slug, true)
- await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible()
- await expect(page.locator(workspaceItemSelector(project.slug)).first()).toBeVisible()
-
- await setWorkspacesEnabled(page, project.slug, false)
- await expect(page.getByRole("button", { name: "New session" }).first()).toBeVisible()
- await expect(page.locator(workspaceItemSelector(project.slug))).toHaveCount(0)
-})
-
-test("can create a workspace", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
-
- await openSidebar(page)
- await setWorkspacesEnabled(page, project.slug, true)
-
- await expect(page.getByRole("button", { name: "New workspace" }).first()).toBeVisible()
-
- await page.getByRole("button", { name: "New workspace" }).first().click()
- const next = await resolveSlug(await waitSlug(page, [project.slug]))
- await waitDir(page, next.directory)
- project.trackDirectory(next.directory)
-
- await openSidebar(page)
-
- await expect
- .poll(
- async () => {
- const item = page.locator(workspaceItemSelector(next.slug)).first()
- try {
- await item.hover({ timeout: 500 })
- return true
- } catch {
- return false
- }
- },
- { timeout: 60_000 },
- )
- .toBe(true)
-
- await expect(page.locator(workspaceItemSelector(next.slug)).first()).toBeVisible()
-})
-
-test("non-git projects keep workspace mode disabled", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
-
- const nonGit = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-e2e-project-nongit-"))
- const nonGitSlug = dirSlug(nonGit)
-
- await fs.writeFile(path.join(nonGit, "README.md"), "# e2e nongit\n")
-
- try {
- await project.open({ extra: [nonGit] })
- await page.goto(`/${nonGitSlug}/session`)
-
- await expect.poll(() => slugFromUrl(page.url()), { timeout: 30_000 }).not.toBe("")
-
- const activeDir = await resolveSlug(slugFromUrl(page.url())).then((item) => item.directory)
- expect(path.basename(activeDir)).toContain("opencode-e2e-project-nongit-")
-
- await openSidebar(page)
- await expect(page.getByRole("button", { name: "New workspace" })).toHaveCount(0)
- await expect(page.getByRole("button", { name: "Create Git repository" })).toBeVisible()
- } finally {
- await cleanupTestProject(nonGit)
- }
-})
-
-test("can rename a workspace", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
-
- const { slug } = await setupWorkspaceTest(page, project)
-
- const rename = `e2e workspace ${Date.now()}`
- const menu = await openWorkspaceMenu(page, slug)
- await clickMenuItem(menu, /^Rename$/i, { force: true })
-
- await expect(menu).toHaveCount(0)
-
- const item = page.locator(workspaceItemSelector(slug)).first()
- await expect(item).toBeVisible()
- const input = item.locator(inlineInputSelector).first()
- const shown = await input
- .isVisible()
- .then((x) => x)
- .catch(() => false)
- if (!shown) {
- const retry = await openWorkspaceMenu(page, slug)
- await clickMenuItem(retry, /^Rename$/i, { force: true })
- await expect(retry).toHaveCount(0)
- }
- await expect(input).toBeVisible()
- await input.fill(rename)
- await input.press("Enter")
- await expect(item).toContainText(rename)
-})
-
-test("can reset a workspace", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
-
- const { slug, directory: createdDir } = await setupWorkspaceTest(page, project)
-
- const readme = path.join(createdDir, "README.md")
- const extra = path.join(createdDir, `e2e_reset_${Date.now()}.txt`)
- const original = await fs.readFile(readme, "utf8")
- const dirty = `${original.trimEnd()}\n\nchange_${Date.now()}\n`
- await fs.writeFile(readme, dirty, "utf8")
- await fs.writeFile(extra, `created_${Date.now()}\n`, "utf8")
-
- await expect
- .poll(async () => {
- return await fs
- .stat(extra)
- .then(() => true)
- .catch(() => false)
- })
- .toBe(true)
-
- await expect
- .poll(async () => {
- const files = await project.sdk.file
- .status({ directory: createdDir })
- .then((r) => r.data ?? [])
- .catch(() => [])
- return files.length
- })
- .toBeGreaterThan(0)
-
- const menu = await openWorkspaceMenu(page, slug)
- await clickMenuItem(menu, /^Reset$/i, { force: true })
- await confirmDialog(page, /^Reset workspace$/i)
-
- await expect
- .poll(
- async () => {
- const files = await project.sdk.file
- .status({ directory: createdDir })
- .then((r) => r.data ?? [])
- .catch(() => [])
- return files.length
- },
- { timeout: 120_000 },
- )
- .toBe(0)
-
- await expect.poll(() => fs.readFile(readme, "utf8"), { timeout: 120_000 }).toBe(original)
-
- await expect
- .poll(async () => {
- return await fs
- .stat(extra)
- .then(() => true)
- .catch(() => false)
- })
- .toBe(false)
-})
-
-test("can reorder workspaces by drag and drop", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
- const rootSlug = project.slug
-
- const listSlugs = async () => {
- const nodes = page.locator('[data-component="sidebar-nav-desktop"] [data-component="workspace-item"]')
- const slugs = await nodes.evaluateAll((els) => {
- return els.map((el) => el.getAttribute("data-workspace") ?? "").filter((x) => x.length > 0)
- })
- return slugs
- }
-
- const waitReady = async (slug: string) => {
- await expect
- .poll(
- async () => {
- const item = page.locator(workspaceItemSelector(slug)).first()
- try {
- await item.hover({ timeout: 500 })
- return true
- } catch {
- return false
- }
- },
- { timeout: 60_000 },
- )
- .toBe(true)
- }
-
- const drag = async (from: string, to: string) => {
- const src = page.locator(workspaceItemSelector(from)).first()
- const dst = page.locator(workspaceItemSelector(to)).first()
-
- const a = await src.boundingBox()
- const b = await dst.boundingBox()
- if (!a || !b) throw new Error("Failed to resolve workspace drag bounds")
-
- await page.mouse.move(a.x + a.width / 2, a.y + a.height / 2)
- await page.mouse.down()
- await page.mouse.move(b.x + b.width / 2, b.y + b.height / 2, { steps: 12 })
- await page.mouse.up()
- }
-
- await openSidebar(page)
-
- await setWorkspacesEnabled(page, rootSlug, true)
-
- const workspaces = [] as { directory: string; slug: string }[]
- for (const _ of [0, 1]) {
- const prev = slugFromUrl(page.url())
- await page.getByRole("button", { name: "New workspace" }).first().click()
- const next = await resolveSlug(await waitSlug(page, [rootSlug, prev]))
- await waitDir(page, next.directory)
- project.trackDirectory(next.directory)
- workspaces.push(next)
-
- await openSidebar(page)
- }
-
- if (workspaces.length !== 2) throw new Error("Expected two created workspaces")
-
- const a = workspaces[0].slug
- const b = workspaces[1].slug
-
- await waitReady(a)
- await waitReady(b)
-
- const list = async () => {
- const slugs = await listSlugs()
- return slugs.filter((s) => s !== rootSlug && (s === a || s === b)).slice(0, 2)
- }
-
- await expect
- .poll(async () => {
- const slugs = await list()
- return slugs.length === 2
- })
- .toBe(true)
-
- const before = await list()
- const from = before[1]
- const to = before[0]
- if (!from || !to) throw new Error("Failed to resolve initial workspace order")
-
- await drag(from, to)
-
- await expect.poll(async () => await list()).toEqual([from, to])
-})
-
-test("can delete a workspace", async ({ page, project }) => {
- await page.setViewportSize({ width: 1400, height: 800 })
- await project.open()
-
- const rootSlug = project.slug
- await openSidebar(page)
- await setWorkspacesEnabled(page, rootSlug, true)
-
- const created = await project.sdk.worktree.create({ directory: project.directory }).then((res) => res.data)
- if (!created?.directory) throw new Error("Failed to create workspace for delete test")
-
- const directory = created.directory
- const slug = dirSlug(directory)
- project.trackDirectory(directory)
-
- await page.reload()
- await openSidebar(page)
- await expect(page.locator(workspaceItemSelector(slug)).first()).toBeVisible({ timeout: 60_000 })
-
- await expect
- .poll(
- async () => {
- const worktrees = await project.sdk.worktree
- .list()
- .then((r) => r.data ?? [])
- .catch(() => [] as string[])
- return worktrees.includes(directory)
- },
- { timeout: 30_000 },
- )
- .toBe(true)
-
- const menu = await openWorkspaceMenu(page, slug)
- await clickMenuItem(menu, /^Delete$/i, { force: true })
- await confirmDialog(page, /^Delete workspace$/i)
-
- await expect.poll(() => base64Decode(slugFromUrl(page.url()))).toBe(project.directory)
-
- await expect
- .poll(
- async () => {
- const worktrees = await project.sdk.worktree
- .list()
- .then((r) => r.data ?? [])
- .catch(() => [] as string[])
- return worktrees.includes(directory)
- },
- { timeout: 60_000 },
- )
- .toBe(false)
-
- await openSidebar(page)
- await expect(page.locator(workspaceItemSelector(slug))).toHaveCount(0, { timeout: 60_000 })
- await expect(page.locator(workspaceItemSelector(rootSlug)).first()).toBeVisible()
-})