mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-26 18:44:47 +00:00
fix(app): preserve file tree tab on reopen + fix e2e test regressions (#16482)
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
import { test, expect } from "../fixtures"
|
import { test, expect } from "../fixtures"
|
||||||
import { serverName } from "../utils"
|
import { serverNamePattern } from "../utils"
|
||||||
|
|
||||||
test("home renders and shows core entrypoints", async ({ page }) => {
|
test("home renders and shows core entrypoints", async ({ page }) => {
|
||||||
await page.goto("/")
|
await page.goto("/")
|
||||||
|
|
||||||
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()
|
await expect(page.getByRole("button", { name: serverNamePattern })).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("server picker dialog opens from home", async ({ page }) => {
|
test("server picker dialog opens from home", async ({ page }) => {
|
||||||
await page.goto("/")
|
await page.goto("/")
|
||||||
|
|
||||||
const trigger = page.getByRole("button", { name: serverName })
|
const trigger = page.getByRole("button", { name: serverNamePattern })
|
||||||
await expect(trigger).toBeVisible()
|
await expect(trigger).toBeVisible()
|
||||||
await trigger.click()
|
await trigger.click()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { test, expect } from "../fixtures"
|
import { test, expect } from "../fixtures"
|
||||||
import { serverName, serverUrl } from "../utils"
|
import { serverNamePattern, serverUrls } from "../utils"
|
||||||
import { clickListItem, closeDialog, clickMenuItem } from "../actions"
|
import { closeDialog, clickMenuItem } from "../actions"
|
||||||
|
|
||||||
const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"
|
const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"
|
||||||
|
|
||||||
@@ -31,10 +31,9 @@ test("can set a default server on web", async ({ page, gotoSession }) => {
|
|||||||
const dialog = page.getByRole("dialog")
|
const dialog = page.getByRole("dialog")
|
||||||
await expect(dialog).toBeVisible()
|
await expect(dialog).toBeVisible()
|
||||||
|
|
||||||
const row = dialog.locator('[data-slot="list-item"]').filter({ hasText: serverName }).first()
|
await expect(dialog.getByText(serverNamePattern).first()).toBeVisible()
|
||||||
await expect(row).toBeVisible()
|
|
||||||
|
|
||||||
const menuTrigger = row.locator('[data-slot="dropdown-menu-trigger"]').first()
|
const menuTrigger = dialog.locator('[data-slot="dropdown-menu-trigger"]').first()
|
||||||
await expect(menuTrigger).toBeVisible()
|
await expect(menuTrigger).toBeVisible()
|
||||||
await menuTrigger.click({ force: true })
|
await menuTrigger.click({ force: true })
|
||||||
|
|
||||||
@@ -42,14 +41,18 @@ test("can set a default server on web", async ({ page, gotoSession }) => {
|
|||||||
await expect(menu).toBeVisible()
|
await expect(menu).toBeVisible()
|
||||||
await clickMenuItem(menu, /set as default/i)
|
await clickMenuItem(menu, /set as default/i)
|
||||||
|
|
||||||
await expect.poll(() => page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)).toBe(serverUrl)
|
await expect
|
||||||
await expect(row.getByText("Default", { exact: true })).toBeVisible()
|
.poll(async () =>
|
||||||
|
serverUrls.includes((await page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)) ?? ""),
|
||||||
|
)
|
||||||
|
.toBe(true)
|
||||||
|
await expect(dialog.getByText("Default", { exact: true })).toBeVisible()
|
||||||
|
|
||||||
await closeDialog(page, dialog)
|
await closeDialog(page, dialog)
|
||||||
|
|
||||||
await ensurePopoverOpen()
|
await ensurePopoverOpen()
|
||||||
|
|
||||||
const serverRow = popover.locator("button").filter({ hasText: serverName }).first()
|
const serverRow = popover.locator("button").filter({ hasText: serverNamePattern }).first()
|
||||||
await expect(serverRow).toBeVisible()
|
await expect(serverRow).toBeVisible()
|
||||||
await expect(serverRow.getByText("Default", { exact: true })).toBeVisible()
|
await expect(serverRow.getByText("Default", { exact: true })).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ const expanded = async (el: { getAttribute: (name: string) => Promise<string | n
|
|||||||
test("review panel can be toggled via keybind", async ({ page, gotoSession }) => {
|
test("review panel can be toggled via keybind", async ({ page, gotoSession }) => {
|
||||||
await gotoSession()
|
await gotoSession()
|
||||||
|
|
||||||
|
const reviewPanel = page.locator("#review-panel")
|
||||||
|
|
||||||
const treeToggle = page.getByRole("button", { name: "Toggle file tree" }).first()
|
const treeToggle = page.getByRole("button", { name: "Toggle file tree" }).first()
|
||||||
await expect(treeToggle).toBeVisible()
|
await expect(treeToggle).toBeVisible()
|
||||||
if (await expanded(treeToggle)) await treeToggle.click()
|
if (await expanded(treeToggle)) await treeToggle.click()
|
||||||
@@ -19,13 +21,13 @@ test("review panel can be toggled via keybind", async ({ page, gotoSession }) =>
|
|||||||
await expect(reviewToggle).toBeVisible()
|
await expect(reviewToggle).toBeVisible()
|
||||||
if (await expanded(reviewToggle)) await reviewToggle.click()
|
if (await expanded(reviewToggle)) await reviewToggle.click()
|
||||||
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
||||||
await expect(page.locator("#review-panel")).toHaveCount(0)
|
await expect(reviewPanel).toHaveAttribute("aria-hidden", "true")
|
||||||
|
|
||||||
await page.keyboard.press(`${modKey}+Shift+R`)
|
await page.keyboard.press(`${modKey}+Shift+R`)
|
||||||
await expect(reviewToggle).toHaveAttribute("aria-expanded", "true")
|
await expect(reviewToggle).toHaveAttribute("aria-expanded", "true")
|
||||||
await expect(page.locator("#review-panel")).toBeVisible()
|
await expect(reviewPanel).toHaveAttribute("aria-hidden", "false")
|
||||||
|
|
||||||
await page.keyboard.press(`${modKey}+Shift+R`)
|
await page.keyboard.press(`${modKey}+Shift+R`)
|
||||||
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
||||||
await expect(page.locator("#review-panel")).toHaveCount(0)
|
await expect(reviewPanel).toHaveAttribute("aria-hidden", "true")
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ test("file tree can expand folders and open a file", async ({ page, gotoSession
|
|||||||
await tab.click()
|
await tab.click()
|
||||||
await expect(tab).toHaveAttribute("aria-selected", "true")
|
await expect(tab).toHaveAttribute("aria-selected", "true")
|
||||||
|
|
||||||
|
await toggle.click()
|
||||||
|
await expect(toggle).toHaveAttribute("aria-expanded", "false")
|
||||||
|
|
||||||
|
await toggle.click()
|
||||||
|
await expect(toggle).toHaveAttribute("aria-expanded", "true")
|
||||||
|
await expect(allTab).toHaveAttribute("aria-selected", "true")
|
||||||
|
|
||||||
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
||||||
await expect(viewer).toBeVisible()
|
await expect(viewer).toBeVisible()
|
||||||
await expect(viewer).toContainText("export default function FileTree")
|
await expect(viewer).toContainText("export default function FileTree")
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ async function seedConversation(input: {
|
|||||||
.toBe(true)
|
.toBe(true)
|
||||||
|
|
||||||
if (!userMessageID) throw new Error("Expected a user message id")
|
if (!userMessageID) throw new Error("Expected a user message id")
|
||||||
await expect(input.page.locator(`[data-message-id="${userMessageID}"]`).first()).toBeVisible({ timeout: 30_000 })
|
await expect(input.page.locator(`[data-message-id="${userMessageID}"]`)).toHaveCount(1, { timeout: 30_000 })
|
||||||
return { prompt, userMessageID }
|
return { prompt, userMessageID }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ test("slash redo clears revert and restores latest state", async ({ page, withPr
|
|||||||
.toBeUndefined()
|
.toBeUndefined()
|
||||||
|
|
||||||
await expect(seeded.prompt).not.toContainText(token)
|
await expect(seeded.prompt).not.toContainText(token)
|
||||||
await expect(page.locator(`[data-message-id="${seeded.userMessageID}"]`).first()).toBeVisible()
|
await expect(page.locator(`[data-message-id="${seeded.userMessageID}"]`)).toHaveCount(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -158,8 +158,8 @@ test("slash undo/redo traverses multi-step revert stack", async ({ page, withPro
|
|||||||
const firstMessage = page.locator(`[data-message-id="${first.userMessageID}"]`)
|
const firstMessage = page.locator(`[data-message-id="${first.userMessageID}"]`)
|
||||||
const secondMessage = page.locator(`[data-message-id="${second.userMessageID}"]`)
|
const secondMessage = page.locator(`[data-message-id="${second.userMessageID}"]`)
|
||||||
|
|
||||||
await expect(firstMessage.first()).toBeVisible()
|
await expect(firstMessage).toHaveCount(1)
|
||||||
await expect(secondMessage.first()).toBeVisible()
|
await expect(secondMessage).toHaveCount(1)
|
||||||
|
|
||||||
await second.prompt.click()
|
await second.prompt.click()
|
||||||
await page.keyboard.press(`${modKey}+A`)
|
await page.keyboard.press(`${modKey}+A`)
|
||||||
@@ -176,7 +176,7 @@ test("slash undo/redo traverses multi-step revert stack", async ({ page, withPro
|
|||||||
})
|
})
|
||||||
.toBe(second.userMessageID)
|
.toBe(second.userMessageID)
|
||||||
|
|
||||||
await expect(firstMessage.first()).toBeVisible()
|
await expect(firstMessage).toHaveCount(1)
|
||||||
await expect(secondMessage).toHaveCount(0)
|
await expect(secondMessage).toHaveCount(0)
|
||||||
|
|
||||||
await second.prompt.click()
|
await second.prompt.click()
|
||||||
@@ -210,7 +210,7 @@ test("slash undo/redo traverses multi-step revert stack", async ({ page, withPro
|
|||||||
})
|
})
|
||||||
.toBe(second.userMessageID)
|
.toBe(second.userMessageID)
|
||||||
|
|
||||||
await expect(firstMessage.first()).toBeVisible()
|
await expect(firstMessage).toHaveCount(1)
|
||||||
await expect(secondMessage).toHaveCount(0)
|
await expect(secondMessage).toHaveCount(0)
|
||||||
|
|
||||||
await second.prompt.click()
|
await second.prompt.click()
|
||||||
@@ -226,8 +226,8 @@ test("slash undo/redo traverses multi-step revert stack", async ({ page, withPro
|
|||||||
})
|
})
|
||||||
.toBeUndefined()
|
.toBeUndefined()
|
||||||
|
|
||||||
await expect(firstMessage.first()).toBeVisible()
|
await expect(firstMessage).toHaveCount(1)
|
||||||
await expect(secondMessage.first()).toBeVisible()
|
await expect(secondMessage).toHaveCount(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,22 @@ export const serverPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096"
|
|||||||
export const serverUrl = `http://${serverHost}:${serverPort}`
|
export const serverUrl = `http://${serverHost}:${serverPort}`
|
||||||
export const serverName = `${serverHost}:${serverPort}`
|
export const serverName = `${serverHost}:${serverPort}`
|
||||||
|
|
||||||
|
const localHosts = ["127.0.0.1", "localhost"]
|
||||||
|
|
||||||
|
const serverLabels = (() => {
|
||||||
|
const url = new URL(serverUrl)
|
||||||
|
if (!localHosts.includes(url.hostname)) return [serverName]
|
||||||
|
return localHosts.map((host) => `${host}:${url.port}`)
|
||||||
|
})()
|
||||||
|
|
||||||
|
export const serverNames = [...new Set(serverLabels)]
|
||||||
|
|
||||||
|
export const serverUrls = serverNames.map((name) => `http://${name}`)
|
||||||
|
|
||||||
|
const escape = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
||||||
|
|
||||||
|
export const serverNamePattern = new RegExp(`(?:${serverNames.map(escape).join("|")})`)
|
||||||
|
|
||||||
export const modKey = process.platform === "darwin" ? "Meta" : "Control"
|
export const modKey = process.platform === "darwin" ? "Meta" : "Control"
|
||||||
export const terminalToggleKey = "Control+Backquote"
|
export const terminalToggleKey = "Control+Backquote"
|
||||||
|
|
||||||
|
|||||||
@@ -1038,23 +1038,6 @@ export default function Page() {
|
|||||||
tabs().setActive(next)
|
tabs().setActive(next)
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(
|
|
||||||
on(
|
|
||||||
() => layout.fileTree.opened(),
|
|
||||||
(opened, prev) => {
|
|
||||||
if (prev === undefined) return
|
|
||||||
if (!isDesktop()) return
|
|
||||||
|
|
||||||
if (opened) {
|
|
||||||
const active = tabs().active()
|
|
||||||
const tab = active === "review" || (!active && hasReview()) ? "changes" : "all"
|
|
||||||
layout.fileTree.setTab(tab)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ defer: true },
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const id = params.id
|
const id = params.id
|
||||||
if (!id) return
|
if (!id) return
|
||||||
|
|||||||
Reference in New Issue
Block a user