Skip to content

Commit eaba997

Browse files
committed
Merge branch 'dev' into feat/canceled-prompts-in-history
2 parents f762125 + 222bddc commit eaba997

80 files changed

Lines changed: 2362 additions & 1142 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# web + desktop packages
22
packages/app/ @adamdotdevin
33
packages/tauri/ @adamdotdevin
4+
packages/desktop/src-tauri/ @brendonovich
45
packages/desktop/ @adamdotdevin

bun.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nix/hashes.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"nodeModules": {
3-
"x86_64-linux": "sha256-Uc9UFWrG9bVROt+DmXduXoY409wBBLtBe0G7R41NF8Q=",
4-
"aarch64-linux": "sha256-KTUsuPfWaw2qb26GmEa5tcSeF3+Kx2X5ZP5DE8jJuvQ=",
5-
"aarch64-darwin": "sha256-C650/LVIoeymKnRw9lVO3f5ve9xYZPrO0vOM5pqY2nE=",
6-
"x86_64-darwin": "sha256-xLLI2mNn222ktx6s8rwej3rMzQGl1S1jV/NXmLFg2DU="
3+
"x86_64-linux": "sha256-9XlAYCNdBhw8NmfJoYNjvQYhSn02rFhWvbJtlOnnCjc=",
4+
"aarch64-linux": "sha256-Mdz3gAy8auN7mhMHRaWyH/exHGO9eYDyUMQKqscg6Xc=",
5+
"aarch64-darwin": "sha256-NDB6+NVZ4+9+Yds/cjEGQAn9Tl/LRuEjEH6wV5dTdVg=",
6+
"x86_64-darwin": "sha256-LGJ5TJYgyK8Vn0BliEeJdoblcubj5ZIjvJoUtdVXfvU="
77
}
88
}

packages/app/e2e/actions.ts

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ import {
2121
import type { createSdk } from "./utils"
2222

2323
export async function defocus(page: Page) {
24-
await page.mouse.click(5, 5)
24+
await page
25+
.evaluate(() => {
26+
const el = document.activeElement
27+
if (el instanceof HTMLElement) el.blur()
28+
})
29+
.catch(() => undefined)
2530
}
2631

2732
export async function openPalette(page: Page) {
@@ -68,14 +73,50 @@ export async function toggleSidebar(page: Page) {
6873

6974
export async function openSidebar(page: Page) {
7075
if (!(await isSidebarClosed(page))) return
76+
77+
const button = page.getByRole("button", { name: /toggle sidebar/i }).first()
78+
const visible = await button
79+
.isVisible()
80+
.then((x) => x)
81+
.catch(() => false)
82+
83+
if (visible) await button.click()
84+
if (!visible) await toggleSidebar(page)
85+
86+
const main = page.locator("main")
87+
const opened = await expect(main)
88+
.not.toHaveClass(/xl:border-l/, { timeout: 1500 })
89+
.then(() => true)
90+
.catch(() => false)
91+
92+
if (opened) return
93+
7194
await toggleSidebar(page)
72-
await expect(page.locator("main")).not.toHaveClass(/xl:border-l/)
95+
await expect(main).not.toHaveClass(/xl:border-l/)
7396
}
7497

7598
export async function closeSidebar(page: Page) {
7699
if (await isSidebarClosed(page)) return
100+
101+
const button = page.getByRole("button", { name: /toggle sidebar/i }).first()
102+
const visible = await button
103+
.isVisible()
104+
.then((x) => x)
105+
.catch(() => false)
106+
107+
if (visible) await button.click()
108+
if (!visible) await toggleSidebar(page)
109+
110+
const main = page.locator("main")
111+
const closed = await expect(main)
112+
.toHaveClass(/xl:border-l/, { timeout: 1500 })
113+
.then(() => true)
114+
.catch(() => false)
115+
116+
if (closed) return
117+
77118
await toggleSidebar(page)
78-
await expect(page.locator("main")).toHaveClass(/xl:border-l/)
119+
await expect(main).toHaveClass(/xl:border-l/)
79120
}
80121

81122
export async function openSettings(page: Page) {
@@ -182,13 +223,30 @@ export async function hoverSessionItem(page: Page, sessionID: string) {
182223
}
183224

184225
export async function openSessionMoreMenu(page: Page, sessionID: string) {
185-
const sessionEl = await hoverSessionItem(page, sessionID)
226+
await expect(page).toHaveURL(new RegExp(`/session/${sessionID}(?:[/?#]|$)`))
227+
228+
const scroller = page.locator(".session-scroller").first()
229+
await expect(scroller).toBeVisible()
230+
await expect(scroller.getByRole("heading", { level: 1 }).first()).toBeVisible({ timeout: 30_000 })
231+
232+
const menu = page
233+
.locator(dropdownMenuContentSelector)
234+
.filter({ has: page.getByRole("menuitem", { name: /rename/i }) })
235+
.filter({ has: page.getByRole("menuitem", { name: /archive/i }) })
236+
.filter({ has: page.getByRole("menuitem", { name: /delete/i }) })
237+
.first()
238+
239+
const opened = await menu
240+
.isVisible()
241+
.then((x) => x)
242+
.catch(() => false)
186243

187-
const menuTrigger = sessionEl.locator(dropdownMenuTriggerSelector).first()
244+
if (opened) return menu
245+
246+
const menuTrigger = scroller.getByRole("button", { name: /more options/i }).first()
188247
await expect(menuTrigger).toBeVisible()
189248
await menuTrigger.click()
190249

191-
const menu = page.locator(dropdownMenuContentSelector).first()
192250
await expect(menu).toBeVisible()
193251
return menu
194252
}

packages/app/e2e/fixtures.ts

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { test as base, expect } from "@playwright/test"
2-
import { seedProjects } from "./actions"
1+
import { test as base, expect, type Page } from "@playwright/test"
2+
import { cleanupTestProject, createTestProject, seedProjects } from "./actions"
33
import { promptSelector } from "./selectors"
44
import { createSdk, dirSlug, getWorktree, sessionPath } from "./utils"
55

@@ -8,6 +8,14 @@ export const settingsKey = "settings.v3"
88
type TestFixtures = {
99
sdk: ReturnType<typeof createSdk>
1010
gotoSession: (sessionID?: string) => Promise<void>
11+
withProject: <T>(
12+
callback: (project: {
13+
directory: string
14+
slug: string
15+
gotoSession: (sessionID?: string) => Promise<void>
16+
}) => Promise<T>,
17+
options?: { extra?: string[] },
18+
) => Promise<T>
1119
}
1220

1321
type WorkerFixtures = {
@@ -33,24 +41,47 @@ export const test = base.extend<TestFixtures, WorkerFixtures>({
3341
await use(createSdk(directory))
3442
},
3543
gotoSession: async ({ page, directory }, use) => {
36-
await seedProjects(page, { directory })
37-
await page.addInitScript(() => {
38-
localStorage.setItem(
39-
"opencode.global.dat:model",
40-
JSON.stringify({
41-
recent: [{ providerID: "opencode", modelID: "big-pickle" }],
42-
user: [],
43-
variant: {},
44-
}),
45-
)
46-
})
44+
await seedStorage(page, { directory })
4745

4846
const gotoSession = async (sessionID?: string) => {
4947
await page.goto(sessionPath(directory, sessionID))
5048
await expect(page.locator(promptSelector)).toBeVisible()
5149
}
5250
await use(gotoSession)
5351
},
52+
withProject: async ({ page }, use) => {
53+
await use(async (callback, options) => {
54+
const directory = await createTestProject()
55+
const slug = dirSlug(directory)
56+
await seedStorage(page, { directory, extra: options?.extra })
57+
58+
const gotoSession = async (sessionID?: string) => {
59+
await page.goto(sessionPath(directory, sessionID))
60+
await expect(page.locator(promptSelector)).toBeVisible()
61+
}
62+
63+
try {
64+
await gotoSession()
65+
return await callback({ directory, slug, gotoSession })
66+
} finally {
67+
await cleanupTestProject(directory)
68+
}
69+
})
70+
},
5471
})
5572

73+
async function seedStorage(page: Page, input: { directory: string; extra?: string[] }) {
74+
await seedProjects(page, input)
75+
await page.addInitScript(() => {
76+
localStorage.setItem(
77+
"opencode.global.dat:model",
78+
JSON.stringify({
79+
recent: [{ providerID: "opencode", modelID: "big-pickle" }],
80+
user: [],
81+
variant: {},
82+
}),
83+
)
84+
})
85+
}
86+
5687
export { expect }

0 commit comments

Comments
 (0)