diff options
| author | Dax Raad <[email protected]> | 2026-04-14 23:10:07 -0400 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2026-04-14 23:10:25 -0400 |
| commit | 627159acac04409d7697a6739e2c572c2a010943 (patch) | |
| tree | 5f87465ea69f41aff0cd96ae5411fe438da480b3 /packages/app/e2e/settings | |
| parent | f44aa02e2677b2b89a1a9f517c0ff8990383deaa (diff) | |
| download | opencode-627159acac04409d7697a6739e2c572c2a010943.tar.gz opencode-627159acac04409d7697a6739e2c572c2a010943.zip | |
delete all e2e tests (#22501)
Cherry-picked from ea463e604cdd2a3e83e1c286e39b789455f0d413
Diffstat (limited to 'packages/app/e2e/settings')
| -rw-r--r-- | packages/app/e2e/settings/settings-keybinds.spec.ts | 389 | ||||
| -rw-r--r-- | packages/app/e2e/settings/settings-models.spec.ts | 122 | ||||
| -rw-r--r-- | packages/app/e2e/settings/settings-providers.spec.ts | 136 | ||||
| -rw-r--r-- | packages/app/e2e/settings/settings.spec.ts | 718 |
4 files changed, 0 insertions, 1365 deletions
diff --git a/packages/app/e2e/settings/settings-keybinds.spec.ts b/packages/app/e2e/settings/settings-keybinds.spec.ts deleted file mode 100644 index 4fc50b68d..000000000 --- a/packages/app/e2e/settings/settings-keybinds.spec.ts +++ /dev/null @@ -1,389 +0,0 @@ -import { test, expect } from "../fixtures" -import { openSettings, closeDialog, waitTerminalFocusIdle, withSession } from "../actions" -import { keybindButtonSelector, terminalSelector } from "../selectors" -import { modKey } from "../utils" - -test("changing sidebar toggle keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")).first() - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain("B") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyH`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("H") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["sidebar.toggle"]).toBe("mod+shift+h") - - await closeDialog(page, dialog) - - const button = page.getByRole("button", { name: /toggle sidebar/i }).first() - const initiallyClosed = (await button.getAttribute("aria-expanded")) !== "true" - - await page.keyboard.press(`${modKey}+Shift+H`) - await expect(button).toHaveAttribute("aria-expanded", initiallyClosed ? "true" : "false") - - const afterToggleClosed = (await button.getAttribute("aria-expanded")) !== "true" - expect(afterToggleClosed).toBe(!initiallyClosed) - - await page.keyboard.press(`${modKey}+Shift+H`) - await expect(button).toHaveAttribute("aria-expanded", initiallyClosed ? "false" : "true") - - const finalClosed = (await button.getAttribute("aria-expanded")) !== "true" - expect(finalClosed).toBe(initiallyClosed) -}) - -test("sidebar toggle keybind guards against shortcut conflicts", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain("B") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyP`) - await page.waitForTimeout(100) - - const toast = page.locator('[data-component="toast"]').last() - await expect(toast).toBeVisible() - await expect(toast).toContainText(/already/i) - - await keybindButton.click() - await expect(keybindButton).toContainText("B") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["sidebar.toggle"]).toBeUndefined() - - await closeDialog(page, dialog) -}) - -test("resetting all keybinds to defaults works", async ({ page, gotoSession }) => { - await page.addInitScript(() => { - localStorage.setItem("settings.v3", JSON.stringify({ keybinds: { "sidebar.toggle": "mod+shift+x" } })) - }) - - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) - await expect(keybindButton).toBeVisible() - - const customKeybind = await keybindButton.textContent() - expect(customKeybind).toContain("X") - - const resetButton = dialog.getByRole("button", { name: "Reset to defaults" }) - await expect(resetButton).toBeVisible() - await expect(resetButton).toBeEnabled() - await resetButton.click() - await page.waitForTimeout(100) - - const restoredKeybind = await keybindButton.textContent() - expect(restoredKeybind).toContain("B") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["sidebar.toggle"]).toBeUndefined() - - await closeDialog(page, dialog) -}) - -test("clearing a keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("sidebar.toggle")) - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain("B") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press("Delete") - await page.waitForTimeout(100) - - const clearedKeybind = await keybindButton.textContent() - expect(clearedKeybind).toMatch(/unassigned|press/i) - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["sidebar.toggle"]).toBe("none") - - await closeDialog(page, dialog) - - await page.keyboard.press(`${modKey}+B`) - await page.waitForTimeout(100) - - const stillOnSession = page.url().includes("/session") - expect(stillOnSession).toBe(true) -}) - -test("changing settings open keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("settings.open")) - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain(",") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Slash`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("/") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["settings.open"]).toBe("mod+/") - - await closeDialog(page, dialog) - - const settingsDialog = page.getByRole("dialog") - await expect(settingsDialog).toHaveCount(0) - - await page.keyboard.press(`${modKey}+Slash`) - await page.waitForTimeout(100) - - await expect(settingsDialog).toBeVisible() - - await closeDialog(page, settingsDialog) -}) - -test("changing new session keybind works", async ({ page, sdk, gotoSession }) => { - await withSession(sdk, "test session for keybind", async (session) => { - await gotoSession(session.id) - - const initialUrl = page.url() - expect(initialUrl).toContain(`/session/${session.id}`) - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("session.new")) - await expect(keybindButton).toBeVisible() - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyN`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("N") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["session.new"]).toBe("mod+shift+n") - - await closeDialog(page, dialog) - - await page.keyboard.press(`${modKey}+Shift+N`) - await page.waitForTimeout(200) - - const newUrl = page.url() - expect(newUrl).toMatch(/\/session\/?$/) - expect(newUrl).not.toContain(session.id) - }) -}) - -test("changing file open keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("file.open")) - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain("K") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyF`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("F") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["file.open"]).toBe("mod+shift+f") - - await closeDialog(page, dialog) - - const filePickerDialog = page.getByRole("dialog").filter({ has: page.getByPlaceholder(/search files/i) }) - await expect(filePickerDialog).toHaveCount(0) - - await page.keyboard.press(`${modKey}+Shift+F`) - await page.waitForTimeout(100) - - await expect(filePickerDialog).toBeVisible() - - await page.keyboard.press("Escape") - await expect(filePickerDialog).toHaveCount(0) -}) - -test("changing terminal toggle keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("terminal.toggle")) - await expect(keybindButton).toBeVisible() - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+KeyY`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("Y") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["terminal.toggle"]).toBe("mod+y") - - await closeDialog(page, dialog) - - const terminal = page.locator(terminalSelector) - await expect(terminal).not.toBeVisible() - - await page.keyboard.press(`${modKey}+Y`) - await waitTerminalFocusIdle(page, { term: terminal }) - - await page.keyboard.press(`${modKey}+Y`) - await expect(terminal).not.toBeVisible() -}) - -test("terminal toggle keybind persists after reload", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("terminal.toggle")) - await expect(keybindButton).toBeVisible() - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyY`) - await page.waitForTimeout(100) - - await expect(keybindButton).toContainText("Y") - await closeDialog(page, dialog) - - await page.reload() - - await expect - .poll(async () => { - return await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - if (!raw) return - const parsed = JSON.parse(raw) - return parsed?.keybinds?.["terminal.toggle"] - }) - }) - .toBe("mod+shift+y") - - const reloaded = await openSettings(page) - await reloaded.getByRole("tab", { name: "Shortcuts" }).click() - const reloadedKeybind = reloaded.locator(keybindButtonSelector("terminal.toggle")).first() - await expect(reloadedKeybind).toContainText("Y") - await closeDialog(page, reloaded) -}) - -test("changing command palette keybind works", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - - const keybindButton = dialog.locator(keybindButtonSelector("command.palette")) - await expect(keybindButton).toBeVisible() - - const initialKeybind = await keybindButton.textContent() - expect(initialKeybind).toContain("P") - - await keybindButton.click() - await expect(keybindButton).toHaveText(/press/i) - - await page.keyboard.press(`${modKey}+Shift+KeyK`) - await page.waitForTimeout(100) - - const newKeybind = await keybindButton.textContent() - expect(newKeybind).toContain("K") - - const stored = await page.evaluate(() => { - const raw = localStorage.getItem("settings.v3") - return raw ? JSON.parse(raw) : null - }) - expect(stored?.keybinds?.["command.palette"]).toBe("mod+shift+k") - - await closeDialog(page, dialog) - - const palette = page.getByRole("dialog").filter({ has: page.getByRole("textbox").first() }) - await expect(palette).toHaveCount(0) - - await page.keyboard.press(`${modKey}+Shift+K`) - await page.waitForTimeout(100) - - await expect(palette).toBeVisible() - await expect(palette.getByRole("textbox").first()).toBeVisible() - - await page.keyboard.press("Escape") - await expect(palette).toHaveCount(0) -}) diff --git a/packages/app/e2e/settings/settings-models.spec.ts b/packages/app/e2e/settings/settings-models.spec.ts deleted file mode 100644 index f7397abe8..000000000 --- a/packages/app/e2e/settings/settings-models.spec.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { test, expect } from "../fixtures" -import { promptSelector } from "../selectors" -import { closeDialog, openSettings } from "../actions" - -test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => { - await gotoSession() - - await page.locator(promptSelector).click() - await page.keyboard.type("/model") - - const command = page.locator('[data-slash-id="model.choose"]') - await expect(command).toBeVisible() - await command.hover() - await page.keyboard.press("Enter") - - const picker = page.getByRole("dialog") - await expect(picker).toBeVisible() - - const target = picker.locator('[data-slot="list-item"]').first() - await expect(target).toBeVisible() - - const key = await target.getAttribute("data-key") - if (!key) throw new Error("Failed to resolve model key from list item") - - const name = (await target.locator("span").first().innerText()).trim() - if (!name) throw new Error("Failed to resolve model name from list item") - - await page.keyboard.press("Escape") - await expect(picker).toHaveCount(0) - - const settings = await openSettings(page) - - await settings.getByRole("tab", { name: "Models" }).click() - const search = settings.getByPlaceholder("Search models") - await expect(search).toBeVisible() - await search.fill(name) - - const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() - const input = toggle.locator('[data-slot="switch-input"]') - await expect(toggle).toBeVisible() - await expect(input).toHaveAttribute("aria-checked", "true") - await toggle.locator('[data-slot="switch-control"]').click() - await expect(input).toHaveAttribute("aria-checked", "false") - - await closeDialog(page, settings) - - await page.locator(promptSelector).click() - await page.keyboard.type("/model") - await expect(command).toBeVisible() - await command.hover() - await page.keyboard.press("Enter") - - const pickerAgain = page.getByRole("dialog") - await expect(pickerAgain).toBeVisible() - await expect(pickerAgain.locator('[data-slot="list-item"]').first()).toBeVisible() - - await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toHaveCount(0) - - await page.keyboard.press("Escape") - await expect(pickerAgain).toHaveCount(0) -}) - -test("showing a hidden model restores it to the model picker", async ({ page, gotoSession }) => { - await gotoSession() - - await page.locator(promptSelector).click() - await page.keyboard.type("/model") - - const command = page.locator('[data-slash-id="model.choose"]') - await expect(command).toBeVisible() - await command.hover() - await page.keyboard.press("Enter") - - const picker = page.getByRole("dialog") - await expect(picker).toBeVisible() - - const target = picker.locator('[data-slot="list-item"]').first() - await expect(target).toBeVisible() - - const key = await target.getAttribute("data-key") - if (!key) throw new Error("Failed to resolve model key from list item") - - const name = (await target.locator("span").first().innerText()).trim() - if (!name) throw new Error("Failed to resolve model name from list item") - - await page.keyboard.press("Escape") - await expect(picker).toHaveCount(0) - - const settings = await openSettings(page) - - await settings.getByRole("tab", { name: "Models" }).click() - const search = settings.getByPlaceholder("Search models") - await expect(search).toBeVisible() - await search.fill(name) - - const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() - const input = toggle.locator('[data-slot="switch-input"]') - await expect(toggle).toBeVisible() - await expect(input).toHaveAttribute("aria-checked", "true") - - await toggle.locator('[data-slot="switch-control"]').click() - await expect(input).toHaveAttribute("aria-checked", "false") - - await toggle.locator('[data-slot="switch-control"]').click() - await expect(input).toHaveAttribute("aria-checked", "true") - - await closeDialog(page, settings) - - await page.locator(promptSelector).click() - await page.keyboard.type("/model") - await expect(command).toBeVisible() - await command.hover() - await page.keyboard.press("Enter") - - const pickerAgain = page.getByRole("dialog") - await expect(pickerAgain).toBeVisible() - - await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toBeVisible() - - await page.keyboard.press("Escape") - await expect(pickerAgain).toHaveCount(0) -}) diff --git a/packages/app/e2e/settings/settings-providers.spec.ts b/packages/app/e2e/settings/settings-providers.spec.ts deleted file mode 100644 index a55eb3498..000000000 --- a/packages/app/e2e/settings/settings-providers.spec.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { test, expect } from "../fixtures" -import { closeDialog, openSettings } from "../actions" - -test("custom provider form can be filled and validates input", async ({ page, gotoSession }) => { - await gotoSession() - - const settings = await openSettings(page) - await settings.getByRole("tab", { name: "Providers" }).click() - - const customProviderSection = settings.locator('[data-component="custom-provider-section"]') - await expect(customProviderSection).toBeVisible() - - const connectButton = customProviderSection.getByRole("button", { name: "Connect" }) - await connectButton.click() - - const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) - await expect(providerDialog).toBeVisible() - - await providerDialog.getByLabel("Provider ID").fill("test-provider") - await providerDialog.getByLabel("Display name").fill("Test Provider") - await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/fake") - await providerDialog.getByLabel("API key").fill("fake-key") - - await providerDialog.getByPlaceholder("model-id").first().fill("test-model") - await providerDialog.getByPlaceholder("Display Name").first().fill("Test Model") - - await expect(providerDialog.getByRole("textbox", { name: "Provider ID" })).toHaveValue("test-provider") - await expect(providerDialog.getByRole("textbox", { name: "Display name" })).toHaveValue("Test Provider") - await expect(providerDialog.getByRole("textbox", { name: "Base URL" })).toHaveValue("http://localhost:9999/fake") - await expect(providerDialog.getByRole("textbox", { name: "API key" })).toHaveValue("fake-key") - await expect(providerDialog.getByPlaceholder("model-id").first()).toHaveValue("test-model") - await expect(providerDialog.getByPlaceholder("Display Name").first()).toHaveValue("Test Model") - - await page.keyboard.press("Escape") - await expect(providerDialog).toHaveCount(0) - - await closeDialog(page, settings) -}) - -test("custom provider form shows validation errors", async ({ page, gotoSession }) => { - await gotoSession() - - const settings = await openSettings(page) - await settings.getByRole("tab", { name: "Providers" }).click() - - const customProviderSection = settings.locator('[data-component="custom-provider-section"]') - await customProviderSection.getByRole("button", { name: "Connect" }).click() - - const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) - await expect(providerDialog).toBeVisible() - - await providerDialog.getByLabel("Provider ID").fill("invalid provider id") - await providerDialog.getByLabel("Base URL").fill("not-a-url") - - await providerDialog.getByRole("button", { name: /submit|save/i }).click() - - await expect(providerDialog.locator('[data-slot="input-error"]').filter({ hasText: /lowercase/i })).toBeVisible() - await expect(providerDialog.locator('[data-slot="input-error"]').filter({ hasText: /http/i })).toBeVisible() - - await page.keyboard.press("Escape") - await expect(providerDialog).toHaveCount(0) - - await closeDialog(page, settings) -}) - -test("custom provider form can add and remove models", async ({ page, gotoSession }) => { - await gotoSession() - - const settings = await openSettings(page) - await settings.getByRole("tab", { name: "Providers" }).click() - - const customProviderSection = settings.locator('[data-component="custom-provider-section"]') - await customProviderSection.getByRole("button", { name: "Connect" }).click() - - const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) - await expect(providerDialog).toBeVisible() - - await providerDialog.getByLabel("Provider ID").fill("multi-model-test") - await providerDialog.getByLabel("Display name").fill("Multi Model Test") - await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/multi") - - await providerDialog.getByPlaceholder("model-id").first().fill("model-1") - await providerDialog.getByPlaceholder("Display Name").first().fill("Model 1") - - const idInputsBefore = await providerDialog.getByPlaceholder("model-id").count() - await providerDialog.getByRole("button", { name: "Add model" }).click() - const idInputsAfter = await providerDialog.getByPlaceholder("model-id").count() - expect(idInputsAfter).toBe(idInputsBefore + 1) - - await providerDialog.getByPlaceholder("model-id").nth(1).fill("model-2") - await providerDialog.getByPlaceholder("Display Name").nth(1).fill("Model 2") - - await expect(providerDialog.getByPlaceholder("model-id").nth(1)).toHaveValue("model-2") - await expect(providerDialog.getByPlaceholder("Display Name").nth(1)).toHaveValue("Model 2") - - await page.keyboard.press("Escape") - await expect(providerDialog).toHaveCount(0) - - await closeDialog(page, settings) -}) - -test("custom provider form can add and remove headers", async ({ page, gotoSession }) => { - await gotoSession() - - const settings = await openSettings(page) - await settings.getByRole("tab", { name: "Providers" }).click() - - const customProviderSection = settings.locator('[data-component="custom-provider-section"]') - await customProviderSection.getByRole("button", { name: "Connect" }).click() - - const providerDialog = page.getByRole("dialog").filter({ has: page.getByText("Custom provider") }) - await expect(providerDialog).toBeVisible() - - await providerDialog.getByLabel("Provider ID").fill("header-test") - await providerDialog.getByLabel("Display name").fill("Header Test") - await providerDialog.getByLabel("Base URL").fill("http://localhost:9999/headers") - - await providerDialog.getByPlaceholder("model-id").first().fill("model-x") - await providerDialog.getByPlaceholder("Display Name").first().fill("Model X") - - const headerInputsBefore = await providerDialog.getByPlaceholder("Header-Name").count() - await providerDialog.getByRole("button", { name: "Add header" }).click() - const headerInputsAfter = await providerDialog.getByPlaceholder("Header-Name").count() - expect(headerInputsAfter).toBe(headerInputsBefore + 1) - - await providerDialog.getByPlaceholder("Header-Name").first().fill("Authorization") - await providerDialog.getByPlaceholder("value").first().fill("Bearer token123") - - await expect(providerDialog.getByPlaceholder("Header-Name").first()).toHaveValue("Authorization") - await expect(providerDialog.getByPlaceholder("value").first()).toHaveValue("Bearer token123") - - await page.keyboard.press("Escape") - await expect(providerDialog).toHaveCount(0) - - await closeDialog(page, settings) -}) diff --git a/packages/app/e2e/settings/settings.spec.ts b/packages/app/e2e/settings/settings.spec.ts deleted file mode 100644 index 6455892cc..000000000 --- a/packages/app/e2e/settings/settings.spec.ts +++ /dev/null @@ -1,718 +0,0 @@ -import { test, expect, settingsKey } from "../fixtures" -import { closeDialog, openSettings } from "../actions" -import { - settingsColorSchemeSelector, - settingsCodeFontSelector, - settingsLanguageSelectSelector, - settingsNotificationsAgentSelector, - settingsNotificationsErrorsSelector, - settingsNotificationsPermissionsSelector, - settingsReleaseNotesSelector, - settingsSoundsAgentSelector, - settingsSoundsErrorsSelector, - settingsSoundsPermissionsSelector, - settingsThemeSelector, - settingsUIFontSelector, - settingsUpdatesStartupSelector, -} from "../selectors" - -test("smoke settings dialog opens, switches tabs, closes", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - - await dialog.getByRole("tab", { name: "Shortcuts" }).click() - await expect(dialog.getByRole("button", { name: "Reset to defaults" })).toBeVisible() - await expect(dialog.getByPlaceholder("Search shortcuts")).toBeVisible() - - await closeDialog(page, dialog) -}) - -test("changing language updates settings labels", async ({ page, gotoSession }) => { - await page.addInitScript(() => { - localStorage.setItem("opencode.global.dat:language", JSON.stringify({ locale: "en" })) - }) - - await gotoSession() - - const dialog = await openSettings(page) - - const heading = dialog.getByRole("heading", { level: 2 }) - await expect(heading).toHaveText("General") - - const select = dialog.locator(settingsLanguageSelectSelector) - await expect(select).toBeVisible() - await select.locator('[data-slot="select-select-trigger"]').click() - - await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Deutsch" }).click() - - await expect(heading).toHaveText("Allgemein") - - await select.locator('[data-slot="select-select-trigger"]').click() - await page.locator('[data-slot="select-select-item"]').filter({ hasText: "English" }).click() - await expect(heading).toHaveText("General") -}) - -test("changing color scheme persists in localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const select = dialog.locator(settingsColorSchemeSelector) - await expect(select).toBeVisible() - - await select.locator('[data-slot="select-select-trigger"]').click() - await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Dark" }).click() - - const colorScheme = await page.evaluate(() => { - return document.documentElement.getAttribute("data-color-scheme") - }) - expect(colorScheme).toBe("dark") - - await select.locator('[data-slot="select-select-trigger"]').click() - await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Light" }).click() - - const lightColorScheme = await page.evaluate(() => { - return document.documentElement.getAttribute("data-color-scheme") - }) - expect(lightColorScheme).toBe("light") -}) - -test("changing theme persists in localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const select = dialog.locator(settingsThemeSelector) - await expect(select).toBeVisible() - - const currentThemeId = await page.evaluate(() => { - return document.documentElement.getAttribute("data-theme") - }) - const currentTheme = (await select.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" - const trigger = select.locator('[data-slot="select-select-trigger"]') - const items = page.locator('[data-slot="select-select-item"]') - - await trigger.click() - const open = await expect - .poll(async () => (await items.count()) > 0, { timeout: 5_000 }) - .toBe(true) - .then(() => true) - .catch(() => false) - if (!open) { - await trigger.click() - await expect.poll(async () => (await items.count()) > 0, { timeout: 10_000 }).toBe(true) - } - await expect(items.first()).toBeVisible() - const count = await items.count() - expect(count).toBeGreaterThan(1) - - const nextTheme = (await items.locator('[data-slot="select-select-item-label"]').allTextContents()) - .map((x) => x.trim()) - .find((x) => x && x !== currentTheme) - expect(nextTheme).toBeTruthy() - - await items.filter({ hasText: nextTheme! }).first().click() - - await page.keyboard.press("Escape") - - const storedThemeId = await page.evaluate(() => { - return localStorage.getItem("opencode-theme-id") - }) - - expect(storedThemeId).not.toBeNull() - expect(storedThemeId).not.toBe(currentThemeId) - - const dataTheme = await page.evaluate(() => { - return document.documentElement.getAttribute("data-theme") - }) - expect(dataTheme).toBe(storedThemeId) -}) - -test("legacy oc-1 theme migrates to oc-2", async ({ page, gotoSession }) => { - await page.addInitScript(() => { - localStorage.setItem("opencode-theme-id", "oc-1") - localStorage.setItem("opencode-theme-css-light", "--background-base:#fff;") - localStorage.setItem("opencode-theme-css-dark", "--background-base:#000;") - }) - - await gotoSession() - - await expect(page.locator("html")).toHaveAttribute("data-theme", "oc-2") - - await expect - .poll(async () => { - return await page.evaluate(() => { - return localStorage.getItem("opencode-theme-id") - }) - }) - .toBe("oc-2") - - await expect - .poll(async () => { - return await page.evaluate(() => { - return localStorage.getItem("opencode-theme-css-light") - }) - }) - .toBeNull() - - await expect - .poll(async () => { - return await page.evaluate(() => { - return localStorage.getItem("opencode-theme-css-dark") - }) - }) - .toBeNull() -}) - -test("typing a code font with spaces persists and updates CSS variable", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const input = dialog.locator(settingsCodeFontSelector) - await expect(input).toBeVisible() - await expect(input).toHaveAttribute("placeholder", "System Mono") - - const initialFontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - const initialUIFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - expect(initialFontFamily).toContain("ui-monospace") - - const next = "Test Mono" - - await input.click() - await input.clear() - await input.pressSequentially(next) - await expect(input).toHaveValue(next) - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - mono: next, - }, - }) - - const newFontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - const newUIFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - expect(newFontFamily).toContain(next) - expect(newFontFamily).not.toBe(initialFontFamily) - expect(newUIFamily).toBe(initialUIFamily) -}) - -test("typing a UI font with spaces persists and updates CSS variable", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const input = dialog.locator(settingsUIFontSelector) - await expect(input).toBeVisible() - await expect(input).toHaveAttribute("placeholder", "System Sans") - - const initialFontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - const initialCodeFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - expect(initialFontFamily).toContain("ui-sans-serif") - - const next = "Test Sans" - - await input.click() - await input.clear() - await input.pressSequentially(next) - await expect(input).toHaveValue(next) - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - sans: next, - }, - }) - - const newFontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - const newCodeFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - expect(newFontFamily).toContain(next) - expect(newFontFamily).not.toBe(initialFontFamily) - expect(newCodeFamily).toBe(initialCodeFamily) -}) - -test("clearing the code font field restores the default placeholder and stack", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const input = dialog.locator(settingsCodeFontSelector) - await expect(input).toBeVisible() - - await input.click() - await input.clear() - await input.pressSequentially("Reset Mono") - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - mono: "Reset Mono", - }, - }) - - await input.clear() - await input.press("Space") - await expect(input).toHaveValue("") - await expect(input).toHaveAttribute("placeholder", "System Mono") - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - mono: "", - }, - }) - - const fontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - expect(fontFamily).toContain("ui-monospace") - expect(fontFamily).not.toContain("Reset Mono") -}) - -test("clearing the UI font field restores the default placeholder and stack", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const input = dialog.locator(settingsUIFontSelector) - await expect(input).toBeVisible() - - await input.click() - await input.clear() - await input.pressSequentially("Reset Sans") - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - sans: "Reset Sans", - }, - }) - - await input.clear() - await input.press("Space") - await expect(input).toHaveValue("") - await expect(input).toHaveAttribute("placeholder", "System Sans") - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - sans: "", - }, - }) - - const fontFamily = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - expect(fontFamily).toContain("ui-sans-serif") - expect(fontFamily).not.toContain("Reset Sans") -}) - -test("color scheme, code font, and UI font rehydrate after reload", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - - const colorSchemeSelect = dialog.locator(settingsColorSchemeSelector) - await expect(colorSchemeSelect).toBeVisible() - await colorSchemeSelect.locator('[data-slot="select-select-trigger"]').click() - await page.locator('[data-slot="select-select-item"]').filter({ hasText: "Dark" }).click() - await expect(page.locator("html")).toHaveAttribute("data-color-scheme", "dark") - - const code = dialog.locator(settingsCodeFontSelector) - const ui = dialog.locator(settingsUIFontSelector) - await expect(code).toBeVisible() - await expect(ui).toBeVisible() - - const initialMono = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - const initialSans = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - - const initialSettings = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - const mono = initialSettings?.appearance?.mono === "Reload Mono" ? "Reload Mono 2" : "Reload Mono" - const sans = initialSettings?.appearance?.sans === "Reload Sans" ? "Reload Sans 2" : "Reload Sans" - - await code.click() - await code.clear() - await code.pressSequentially(mono) - await expect(code).toHaveValue(mono) - - await ui.click() - await ui.clear() - await ui.pressSequentially(sans) - await expect(ui).toHaveValue(sans) - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - mono, - sans, - }, - }) - - const updatedSettings = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - const updatedMono = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - const updatedSans = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - expect(updatedMono).toContain(mono) - expect(updatedMono).not.toBe(initialMono) - expect(updatedSans).toContain(sans) - expect(updatedSans).not.toBe(initialSans) - expect(updatedSettings?.appearance?.mono).toBe(mono) - expect(updatedSettings?.appearance?.sans).toBe(sans) - - await closeDialog(page, dialog) - await page.reload() - - await expect(page.locator("html")).toHaveAttribute("data-color-scheme", "dark") - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - appearance: { - mono, - sans, - }, - }) - - const rehydratedSettings = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - await expect - .poll(async () => { - return await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - }) - .toContain(mono) - - await expect - .poll(async () => { - return await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - }) - .toContain(sans) - - const rehydratedMono = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-mono").trim(), - ) - const rehydratedSans = await page.evaluate(() => - getComputedStyle(document.documentElement).getPropertyValue("--font-family-sans").trim(), - ) - expect(rehydratedMono).toContain(mono) - expect(rehydratedMono).not.toBe(initialMono) - expect(rehydratedSans).toContain(sans) - expect(rehydratedSans).not.toBe(initialSans) - expect(rehydratedSettings?.appearance?.mono).toBe(mono) - expect(rehydratedSettings?.appearance?.sans).toBe(sans) -}) - -test("toggling notification agent switch updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const switchContainer = dialog.locator(settingsNotificationsAgentSelector) - await expect(switchContainer).toBeVisible() - - const toggleInput = switchContainer.locator('[data-slot="switch-input"]') - const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(initialState).toBe(true) - - await switchContainer.locator('[data-slot="switch-control"]').click() - await page.waitForTimeout(100) - - const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(newState).toBe(false) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.notifications?.agent).toBe(false) -}) - -test("toggling notification permissions switch updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const switchContainer = dialog.locator(settingsNotificationsPermissionsSelector) - await expect(switchContainer).toBeVisible() - - const toggleInput = switchContainer.locator('[data-slot="switch-input"]') - const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(initialState).toBe(true) - - await switchContainer.locator('[data-slot="switch-control"]').click() - await page.waitForTimeout(100) - - const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(newState).toBe(false) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.notifications?.permissions).toBe(false) -}) - -test("toggling notification errors switch updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const switchContainer = dialog.locator(settingsNotificationsErrorsSelector) - await expect(switchContainer).toBeVisible() - - const toggleInput = switchContainer.locator('[data-slot="switch-input"]') - const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(initialState).toBe(false) - - await switchContainer.locator('[data-slot="switch-control"]').click() - await page.waitForTimeout(100) - - const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(newState).toBe(true) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.notifications?.errors).toBe(true) -}) - -test("changing sound agent selection persists in localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const select = dialog.locator(settingsSoundsAgentSelector) - await expect(select).toBeVisible() - - await select.locator('[data-slot="select-select-trigger"]').click() - - const items = page.locator('[data-slot="select-select-item"]') - await items.nth(2).click() - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.sounds?.agent).not.toBe("staplebops-01") -}) - -test("selecting none disables agent sound", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const select = dialog.locator(settingsSoundsAgentSelector) - const trigger = select.locator('[data-slot="select-select-trigger"]') - await expect(select).toBeVisible() - await expect(trigger).toBeEnabled() - - await trigger.click() - const items = page.locator('[data-slot="select-select-item"]') - await expect(items.first()).toBeVisible() - await items.first().click() - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.sounds?.agentEnabled).toBe(false) -}) - -test("changing permissions and errors sounds updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const permissionsSelect = dialog.locator(settingsSoundsPermissionsSelector) - const errorsSelect = dialog.locator(settingsSoundsErrorsSelector) - await expect(permissionsSelect).toBeVisible() - await expect(errorsSelect).toBeVisible() - - const initial = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - const permissionsCurrent = - (await permissionsSelect.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" - await permissionsSelect.locator('[data-slot="select-select-trigger"]').click() - const permissionItems = page.locator('[data-slot="select-select-item"]') - expect(await permissionItems.count()).toBeGreaterThan(1) - if (permissionsCurrent) { - await permissionItems.filter({ hasNotText: permissionsCurrent }).first().click() - } - if (!permissionsCurrent) { - await permissionItems.nth(1).click() - } - - const errorsCurrent = - (await errorsSelect.locator('[data-slot="select-select-trigger-value"]').textContent())?.trim() ?? "" - await errorsSelect.locator('[data-slot="select-select-trigger"]').click() - const errorItems = page.locator('[data-slot="select-select-item"]') - expect(await errorItems.count()).toBeGreaterThan(1) - if (errorsCurrent) { - await errorItems.filter({ hasNotText: errorsCurrent }).first().click() - } - if (!errorsCurrent) { - await errorItems.nth(1).click() - } - - await expect - .poll(async () => { - return await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - }) - .toMatchObject({ - sounds: { - permissions: expect.any(String), - errors: expect.any(String), - }, - }) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.sounds?.permissions).not.toBe(initial?.sounds?.permissions) - expect(stored?.sounds?.errors).not.toBe(initial?.sounds?.errors) -}) - -test("toggling updates startup switch updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const switchContainer = dialog.locator(settingsUpdatesStartupSelector) - await expect(switchContainer).toBeVisible() - - const toggleInput = switchContainer.locator('[data-slot="switch-input"]') - - const isDisabled = await toggleInput.evaluate((el: HTMLInputElement) => el.disabled) - if (isDisabled) { - test.skip() - return - } - - const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(initialState).toBe(true) - - await switchContainer.locator('[data-slot="switch-control"]').click() - await page.waitForTimeout(100) - - const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(newState).toBe(false) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.updates?.startup).toBe(false) -}) - -test("toggling release notes switch updates localStorage", async ({ page, gotoSession }) => { - await gotoSession() - - const dialog = await openSettings(page) - const switchContainer = dialog.locator(settingsReleaseNotesSelector) - await expect(switchContainer).toBeVisible() - - const toggleInput = switchContainer.locator('[data-slot="switch-input"]') - const initialState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(initialState).toBe(true) - - await switchContainer.locator('[data-slot="switch-control"]').click() - await page.waitForTimeout(100) - - const newState = await toggleInput.evaluate((el: HTMLInputElement) => el.checked) - expect(newState).toBe(false) - - const stored = await page.evaluate((key) => { - const raw = localStorage.getItem(key) - return raw ? JSON.parse(raw) : null - }, settingsKey) - - expect(stored?.general?.releaseNotes).toBe(false) -}) |
