test(app): e2e utilities
This commit is contained in:
@@ -1,24 +1,21 @@
|
|||||||
import { test, expect } from "@playwright/test"
|
import { test, expect } from "@playwright/test"
|
||||||
|
import { serverName } from "./utils"
|
||||||
|
|
||||||
test("home renders and shows an open project entrypoint", async ({ page }) => {
|
test("home renders and shows core entrypoints", async ({ page }) => {
|
||||||
await page.goto("/")
|
await page.goto("/")
|
||||||
|
|
||||||
await expect(page.getByText("Recent projects").or(page.getByText("No recent projects"))).toBeVisible()
|
|
||||||
await expect(page.getByRole("button", { name: "Open project" }).first()).toBeVisible()
|
await expect(page.getByRole("button", { name: "Open project" }).first()).toBeVisible()
|
||||||
|
await expect(page.getByRole("button", { name: serverName })).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("server picker dialog opens from home", async ({ page }) => {
|
test("server picker dialog opens from home", async ({ page }) => {
|
||||||
const host = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
|
||||||
const port = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|
||||||
const name = `${host}:${port}`
|
|
||||||
|
|
||||||
await page.goto("/")
|
await page.goto("/")
|
||||||
|
|
||||||
const trigger = page.getByRole("button", { name })
|
const trigger = page.getByRole("button", { name: serverName })
|
||||||
await expect(trigger).toBeVisible()
|
await expect(trigger).toBeVisible()
|
||||||
await trigger.click()
|
await trigger.click()
|
||||||
|
|
||||||
const dialog = page.getByRole("dialog", { name: "Servers" })
|
const dialog = page.getByRole("dialog")
|
||||||
await expect(dialog).toBeVisible()
|
await expect(dialog).toBeVisible()
|
||||||
await expect(dialog.getByPlaceholder("Search servers")).toBeVisible()
|
await expect(dialog.getByRole("textbox").first()).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,24 +1,11 @@
|
|||||||
import { test, expect } from "@playwright/test"
|
import { test, expect } from "@playwright/test"
|
||||||
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
|
import { dirPath, dirSlug, getWorktree, promptSelector } from "./utils"
|
||||||
import { base64Encode } from "@opencode-ai/util/encode"
|
|
||||||
|
|
||||||
const host = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
|
||||||
const port = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|
||||||
const url = `http://${host}:${port}`
|
|
||||||
|
|
||||||
async function getWorktree() {
|
|
||||||
const sdk = createOpencodeClient({ baseUrl: url, throwOnError: true })
|
|
||||||
const result = await sdk.path.get()
|
|
||||||
const data = result.data
|
|
||||||
if (!data?.worktree) throw new Error(`Failed to resolve a worktree from ${url}/path`)
|
|
||||||
return data.worktree
|
|
||||||
}
|
|
||||||
|
|
||||||
test("project route redirects to /session", async ({ page }) => {
|
test("project route redirects to /session", async ({ page }) => {
|
||||||
const directory = await getWorktree()
|
const directory = await getWorktree()
|
||||||
const slug = base64Encode(directory)
|
const slug = dirSlug(directory)
|
||||||
|
|
||||||
await page.goto(`/${slug}`)
|
await page.goto(dirPath(directory))
|
||||||
await expect(page).toHaveURL(new RegExp(`/${slug}/session`))
|
await expect(page).toHaveURL(new RegExp(`/${slug}/session`))
|
||||||
await expect(page.locator('[data-component="prompt-input"]')).toBeVisible()
|
await expect(page.locator(promptSelector)).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,29 +1,11 @@
|
|||||||
import { test, expect } from "@playwright/test"
|
import { test, expect } from "@playwright/test"
|
||||||
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
|
import { gotoSession, modKey, promptSelector } from "./utils"
|
||||||
import { base64Encode } from "@opencode-ai/util/encode"
|
|
||||||
|
|
||||||
const host = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
|
||||||
const port = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|
||||||
const url = `http://${host}:${port}`
|
|
||||||
|
|
||||||
async function getWorktree() {
|
|
||||||
const sdk = createOpencodeClient({ baseUrl: url, throwOnError: true })
|
|
||||||
const result = await sdk.path.get()
|
|
||||||
const data = result.data
|
|
||||||
if (!data?.worktree) throw new Error(`Failed to resolve a worktree from ${url}/path`)
|
|
||||||
return data.worktree
|
|
||||||
}
|
|
||||||
|
|
||||||
const mod = process.platform === "darwin" ? "Meta" : "Control"
|
|
||||||
|
|
||||||
test("search palette opens and closes", async ({ page }) => {
|
test("search palette opens and closes", async ({ page }) => {
|
||||||
const directory = await getWorktree()
|
await gotoSession(page)
|
||||||
const slug = base64Encode(directory)
|
await expect(page.locator(promptSelector)).toBeVisible()
|
||||||
|
|
||||||
await page.goto(`/${slug}/session`)
|
await page.keyboard.press(`${modKey}+P`)
|
||||||
await expect(page.locator('[data-component="prompt-input"]')).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press(`${mod}+P`)
|
|
||||||
|
|
||||||
const dialog = page.getByRole("dialog")
|
const dialog = page.getByRole("dialog")
|
||||||
await expect(dialog).toBeVisible()
|
await expect(dialog).toBeVisible()
|
||||||
|
|||||||
@@ -1,22 +1,9 @@
|
|||||||
import { test, expect } from "@playwright/test"
|
import { test, expect } from "@playwright/test"
|
||||||
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
|
import { createSdk, getWorktree, promptSelector, sessionPath } from "./utils"
|
||||||
import { base64Encode } from "@opencode-ai/util/encode"
|
|
||||||
|
|
||||||
const host = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
|
||||||
const port = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|
||||||
const url = `http://${host}:${port}`
|
|
||||||
|
|
||||||
async function getWorktree() {
|
|
||||||
const sdk = createOpencodeClient({ baseUrl: url, throwOnError: true })
|
|
||||||
const result = await sdk.path.get()
|
|
||||||
const data = result.data
|
|
||||||
if (!data?.worktree) throw new Error(`Failed to resolve a worktree from ${url}/path`)
|
|
||||||
return data.worktree
|
|
||||||
}
|
|
||||||
|
|
||||||
test("can open an existing session and type into the prompt", async ({ page }) => {
|
test("can open an existing session and type into the prompt", async ({ page }) => {
|
||||||
const directory = await getWorktree()
|
const directory = await getWorktree()
|
||||||
const sdk = createOpencodeClient({ baseUrl: url, directory, throwOnError: true })
|
const sdk = createSdk(directory)
|
||||||
const title = `e2e smoke ${Date.now()}`
|
const title = `e2e smoke ${Date.now()}`
|
||||||
const created = await sdk.session.create({ title }).then((r) => r.data)
|
const created = await sdk.session.create({ title }).then((r) => r.data)
|
||||||
|
|
||||||
@@ -24,9 +11,9 @@ test("can open an existing session and type into the prompt", async ({ page }) =
|
|||||||
const sessionID = created.id
|
const sessionID = created.id
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await page.goto(`/${base64Encode(directory)}/session/${sessionID}`)
|
await page.goto(sessionPath(directory, sessionID))
|
||||||
|
|
||||||
const prompt = page.locator('[data-component="prompt-input"]')
|
const prompt = page.locator(promptSelector)
|
||||||
await expect(prompt).toBeVisible()
|
await expect(prompt).toBeVisible()
|
||||||
|
|
||||||
await prompt.click()
|
await prompt.click()
|
||||||
|
|||||||
@@ -1,33 +1,17 @@
|
|||||||
import { test, expect } from "@playwright/test"
|
import { test, expect } from "@playwright/test"
|
||||||
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
|
import { gotoSession, promptSelector, terminalSelector, terminalToggleKey } from "./utils"
|
||||||
import { base64Encode } from "@opencode-ai/util/encode"
|
|
||||||
|
|
||||||
const host = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
|
||||||
const port = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|
||||||
const url = `http://${host}:${port}`
|
|
||||||
|
|
||||||
async function getWorktree() {
|
|
||||||
const sdk = createOpencodeClient({ baseUrl: url, throwOnError: true })
|
|
||||||
const result = await sdk.path.get()
|
|
||||||
const data = result.data
|
|
||||||
if (!data?.worktree) throw new Error(`Failed to resolve a worktree from ${url}/path`)
|
|
||||||
return data.worktree
|
|
||||||
}
|
|
||||||
|
|
||||||
test("terminal panel can be toggled", async ({ page }) => {
|
test("terminal panel can be toggled", async ({ page }) => {
|
||||||
const directory = await getWorktree()
|
await gotoSession(page)
|
||||||
const slug = base64Encode(directory)
|
await expect(page.locator(promptSelector)).toBeVisible()
|
||||||
|
|
||||||
await page.goto(`/${slug}/session`)
|
const terminal = page.locator(terminalSelector)
|
||||||
await expect(page.locator('[data-component="prompt-input"]')).toBeVisible()
|
|
||||||
|
|
||||||
const terminal = page.locator('[data-component="terminal"]')
|
|
||||||
const initiallyOpen = await terminal.isVisible()
|
const initiallyOpen = await terminal.isVisible()
|
||||||
if (initiallyOpen) {
|
if (initiallyOpen) {
|
||||||
await page.keyboard.press("Control+Backquote")
|
await page.keyboard.press(terminalToggleKey)
|
||||||
await expect(terminal).toHaveCount(0)
|
await expect(terminal).toHaveCount(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.keyboard.press("Control+Backquote")
|
await page.keyboard.press(terminalToggleKey)
|
||||||
await expect(terminal).toBeVisible()
|
await expect(terminal).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|||||||
45
packages/app/e2e/utils.ts
Normal file
45
packages/app/e2e/utils.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
|
||||||
|
import { base64Encode } from "@opencode-ai/util/encode"
|
||||||
|
import type { Page } from "@playwright/test"
|
||||||
|
|
||||||
|
export const serverHost = process.env.PLAYWRIGHT_SERVER_HOST ?? "localhost"
|
||||||
|
export const serverPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
||||||
|
|
||||||
|
export const serverUrl = `http://${serverHost}:${serverPort}`
|
||||||
|
export const serverName = `${serverHost}:${serverPort}`
|
||||||
|
|
||||||
|
export const modKey = process.platform === "darwin" ? "Meta" : "Control"
|
||||||
|
export const terminalToggleKey = "Control+Backquote"
|
||||||
|
|
||||||
|
export const promptSelector = '[data-component="prompt-input"]'
|
||||||
|
export const terminalSelector = '[data-component="terminal"]'
|
||||||
|
|
||||||
|
export function createSdk(directory?: string) {
|
||||||
|
return createOpencodeClient({ baseUrl: serverUrl, directory, throwOnError: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getWorktree() {
|
||||||
|
const sdk = createSdk()
|
||||||
|
const result = await sdk.path.get()
|
||||||
|
const data = result.data
|
||||||
|
if (!data?.worktree) throw new Error(`Failed to resolve a worktree from ${serverUrl}/path`)
|
||||||
|
return data.worktree
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dirSlug(directory: string) {
|
||||||
|
return base64Encode(directory)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dirPath(directory: string) {
|
||||||
|
return `/${dirSlug(directory)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sessionPath(directory: string, sessionID?: string) {
|
||||||
|
return `${dirPath(directory)}/session${sessionID ? `/${sessionID}` : ""}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function gotoSession(page: Page, sessionID?: string) {
|
||||||
|
const directory = await getWorktree()
|
||||||
|
await page.goto(sessionPath(directory, sessionID))
|
||||||
|
return { directory, slug: dirSlug(directory) }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user