reigncode-app 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +30 -0
- package/Dockerfile +21 -0
- package/README.md +51 -0
- package/bunfig.toml +3 -0
- package/create-effect-simplification-spec.md +515 -0
- package/e2e/AGENTS.md +226 -0
- package/e2e/actions.ts +1018 -0
- package/e2e/app/home.spec.ts +24 -0
- package/e2e/app/navigation.spec.ts +10 -0
- package/e2e/app/palette.spec.ts +20 -0
- package/e2e/app/server-default.spec.ts +58 -0
- package/e2e/app/session.spec.ts +16 -0
- package/e2e/app/titlebar-history.spec.ts +120 -0
- package/e2e/commands/input-focus.spec.ts +15 -0
- package/e2e/commands/panels.spec.ts +33 -0
- package/e2e/commands/tab-close.spec.ts +32 -0
- package/e2e/files/file-open.spec.ts +31 -0
- package/e2e/files/file-tree.spec.ts +56 -0
- package/e2e/files/file-viewer.spec.ts +156 -0
- package/e2e/fixtures.ts +154 -0
- package/e2e/models/model-picker.spec.ts +48 -0
- package/e2e/models/models-visibility.spec.ts +61 -0
- package/e2e/projects/project-edit.spec.ts +43 -0
- package/e2e/projects/projects-close.spec.ts +54 -0
- package/e2e/projects/projects-switch.spec.ts +116 -0
- package/e2e/projects/workspace-new-session.spec.ts +94 -0
- package/e2e/projects/workspaces.spec.ts +375 -0
- package/e2e/prompt/context.spec.ts +95 -0
- package/e2e/prompt/prompt-async.spec.ts +76 -0
- package/e2e/prompt/prompt-drop-file-uri.spec.ts +22 -0
- package/e2e/prompt/prompt-drop-file.spec.ts +30 -0
- package/e2e/prompt/prompt-history.spec.ts +184 -0
- package/e2e/prompt/prompt-mention.spec.ts +26 -0
- package/e2e/prompt/prompt-multiline.spec.ts +24 -0
- package/e2e/prompt/prompt-shell.spec.ts +62 -0
- package/e2e/prompt/prompt-slash-open.spec.ts +22 -0
- package/e2e/prompt/prompt-slash-share.spec.ts +64 -0
- package/e2e/prompt/prompt-slash-terminal.spec.ts +18 -0
- package/e2e/prompt/prompt.spec.ts +55 -0
- package/e2e/selectors.ts +75 -0
- package/e2e/session/session-child-navigation.spec.ts +37 -0
- package/e2e/session/session-composer-dock.spec.ts +530 -0
- package/e2e/session/session-model-persistence.spec.ts +359 -0
- package/e2e/session/session-review.spec.ts +426 -0
- package/e2e/session/session-undo-redo.spec.ts +233 -0
- package/e2e/session/session.spec.ts +174 -0
- package/e2e/settings/settings-keybinds.spec.ts +389 -0
- package/e2e/settings/settings-models.spec.ts +122 -0
- package/e2e/settings/settings-providers.spec.ts +136 -0
- package/e2e/settings/settings.spec.ts +519 -0
- package/e2e/sidebar/sidebar-popover-actions.spec.ts +118 -0
- package/e2e/sidebar/sidebar-session-links.spec.ts +30 -0
- package/e2e/sidebar/sidebar.spec.ts +40 -0
- package/e2e/status/status-popover.spec.ts +94 -0
- package/e2e/terminal/terminal-init.spec.ts +28 -0
- package/e2e/terminal/terminal-reconnect.spec.ts +46 -0
- package/e2e/terminal/terminal-tabs.spec.ts +168 -0
- package/e2e/terminal/terminal.spec.ts +18 -0
- package/e2e/thinking-level.spec.ts +25 -0
- package/e2e/tsconfig.json +9 -0
- package/e2e/utils.ts +63 -0
- package/happydom.ts +75 -0
- package/index.html +23 -0
- package/package.json +77 -0
- package/playwright.config.ts +45 -0
- package/public/_headers +17 -0
- package/public/oc-theme-preload.js +35 -0
- package/script/e2e-local.ts +180 -0
- package/src/addons/serialize.test.ts +319 -0
- package/src/addons/serialize.ts +634 -0
- package/src/app.tsx +308 -0
- package/src/components/debug-bar.tsx +443 -0
- package/src/components/dialog-connect-provider.tsx +617 -0
- package/src/components/dialog-custom-provider-form.ts +158 -0
- package/src/components/dialog-custom-provider.test.ts +80 -0
- package/src/components/dialog-custom-provider.tsx +329 -0
- package/src/components/dialog-edit-project.tsx +255 -0
- package/src/components/dialog-fork.tsx +108 -0
- package/src/components/dialog-manage-models.tsx +101 -0
- package/src/components/dialog-release-notes.tsx +144 -0
- package/src/components/dialog-select-directory.tsx +392 -0
- package/src/components/dialog-select-file.tsx +466 -0
- package/src/components/dialog-select-mcp.tsx +107 -0
- package/src/components/dialog-select-model-unpaid.tsx +137 -0
- package/src/components/dialog-select-model.tsx +220 -0
- package/src/components/dialog-select-provider.tsx +86 -0
- package/src/components/dialog-select-server.tsx +649 -0
- package/src/components/dialog-settings.tsx +73 -0
- package/src/components/file-tree.test.ts +78 -0
- package/src/components/file-tree.tsx +507 -0
- package/src/components/link.tsx +26 -0
- package/src/components/model-tooltip.tsx +91 -0
- package/src/components/prompt-input/attachments.test.ts +44 -0
- package/src/components/prompt-input/attachments.ts +201 -0
- package/src/components/prompt-input/build-request-parts.test.ts +312 -0
- package/src/components/prompt-input/build-request-parts.ts +175 -0
- package/src/components/prompt-input/context-items.tsx +88 -0
- package/src/components/prompt-input/drag-overlay.tsx +25 -0
- package/src/components/prompt-input/editor-dom.test.ts +99 -0
- package/src/components/prompt-input/editor-dom.ts +148 -0
- package/src/components/prompt-input/files.ts +66 -0
- package/src/components/prompt-input/history.test.ts +153 -0
- package/src/components/prompt-input/history.ts +256 -0
- package/src/components/prompt-input/image-attachments.tsx +58 -0
- package/src/components/prompt-input/paste.ts +24 -0
- package/src/components/prompt-input/placeholder.test.ts +48 -0
- package/src/components/prompt-input/placeholder.ts +15 -0
- package/src/components/prompt-input/slash-popover.tsx +141 -0
- package/src/components/prompt-input/submit.test.ts +346 -0
- package/src/components/prompt-input/submit.ts +579 -0
- package/src/components/prompt-input.tsx +1595 -0
- package/src/components/server/server-row.tsx +130 -0
- package/src/components/session/index.ts +5 -0
- package/src/components/session/session-context-breakdown.test.ts +61 -0
- package/src/components/session/session-context-breakdown.ts +132 -0
- package/src/components/session/session-context-format.ts +20 -0
- package/src/components/session/session-context-metrics.test.ts +101 -0
- package/src/components/session/session-context-metrics.ts +82 -0
- package/src/components/session/session-context-tab.tsx +339 -0
- package/src/components/session/session-header.tsx +486 -0
- package/src/components/session/session-new-view.tsx +91 -0
- package/src/components/session/session-sortable-tab.tsx +70 -0
- package/src/components/session/session-sortable-terminal-tab.tsx +193 -0
- package/src/components/session-context-usage.tsx +122 -0
- package/src/components/settings-general.tsx +585 -0
- package/src/components/settings-keybinds.tsx +453 -0
- package/src/components/settings-list.tsx +5 -0
- package/src/components/settings-models.tsx +137 -0
- package/src/components/settings-providers.tsx +251 -0
- package/src/components/status-popover.tsx +419 -0
- package/src/components/terminal.tsx +653 -0
- package/src/components/titlebar-history.test.ts +63 -0
- package/src/components/titlebar-history.ts +57 -0
- package/src/components/titlebar.tsx +312 -0
- package/src/constants/file-picker.ts +89 -0
- package/src/context/command-keybind.test.ts +69 -0
- package/src/context/command.test.ts +25 -0
- package/src/context/command.tsx +437 -0
- package/src/context/comments.test.ts +186 -0
- package/src/context/comments.tsx +243 -0
- package/src/context/file/content-cache.ts +88 -0
- package/src/context/file/path.test.ts +360 -0
- package/src/context/file/path.ts +151 -0
- package/src/context/file/tree-store.ts +170 -0
- package/src/context/file/types.ts +41 -0
- package/src/context/file/view-cache.ts +146 -0
- package/src/context/file/watcher.test.ts +149 -0
- package/src/context/file/watcher.ts +53 -0
- package/src/context/file-content-eviction-accounting.test.ts +65 -0
- package/src/context/file.tsx +280 -0
- package/src/context/global-sdk.tsx +232 -0
- package/src/context/global-sync/bootstrap.ts +206 -0
- package/src/context/global-sync/child-store.test.ts +38 -0
- package/src/context/global-sync/child-store.ts +281 -0
- package/src/context/global-sync/event-reducer.test.ts +552 -0
- package/src/context/global-sync/event-reducer.ts +359 -0
- package/src/context/global-sync/eviction.ts +28 -0
- package/src/context/global-sync/queue.ts +83 -0
- package/src/context/global-sync/session-cache.test.ts +102 -0
- package/src/context/global-sync/session-cache.ts +62 -0
- package/src/context/global-sync/session-load.ts +25 -0
- package/src/context/global-sync/session-prefetch.test.ts +96 -0
- package/src/context/global-sync/session-prefetch.ts +100 -0
- package/src/context/global-sync/session-trim.test.ts +59 -0
- package/src/context/global-sync/session-trim.ts +56 -0
- package/src/context/global-sync/types.ts +133 -0
- package/src/context/global-sync/utils.ts +25 -0
- package/src/context/global-sync.test.ts +122 -0
- package/src/context/global-sync.tsx +408 -0
- package/src/context/highlights.tsx +233 -0
- package/src/context/language.tsx +248 -0
- package/src/context/layout-scroll.test.ts +64 -0
- package/src/context/layout-scroll.ts +126 -0
- package/src/context/layout.test.ts +69 -0
- package/src/context/layout.tsx +937 -0
- package/src/context/local.tsx +422 -0
- package/src/context/model-variant.test.ts +86 -0
- package/src/context/model-variant.ts +52 -0
- package/src/context/models.tsx +163 -0
- package/src/context/notification.tsx +373 -0
- package/src/context/permission-auto-respond.test.ts +102 -0
- package/src/context/permission-auto-respond.ts +51 -0
- package/src/context/permission.tsx +277 -0
- package/src/context/platform.tsx +99 -0
- package/src/context/prompt.tsx +297 -0
- package/src/context/sdk.tsx +49 -0
- package/src/context/server.tsx +295 -0
- package/src/context/settings.tsx +241 -0
- package/src/context/sync-optimistic.test.ts +123 -0
- package/src/context/sync.tsx +618 -0
- package/src/context/terminal-title.ts +51 -0
- package/src/context/terminal.test.ts +82 -0
- package/src/context/terminal.tsx +437 -0
- package/src/entry.tsx +144 -0
- package/src/env.d.ts +18 -0
- package/src/hooks/use-providers.ts +44 -0
- package/src/i18n/ar.ts +855 -0
- package/src/i18n/br.ts +867 -0
- package/src/i18n/bs.ts +943 -0
- package/src/i18n/da.ts +937 -0
- package/src/i18n/de.ts +879 -0
- package/src/i18n/en.ts +948 -0
- package/src/i18n/es.ts +950 -0
- package/src/i18n/fr.ts +878 -0
- package/src/i18n/ja.ts +861 -0
- package/src/i18n/ko.ts +860 -0
- package/src/i18n/no.ts +944 -0
- package/src/i18n/parity.test.ts +32 -0
- package/src/i18n/pl.ts +865 -0
- package/src/i18n/ru.ts +946 -0
- package/src/i18n/th.ts +933 -0
- package/src/i18n/tr.ts +952 -0
- package/src/i18n/zh.ts +930 -0
- package/src/i18n/zht.ts +925 -0
- package/src/index.css +29 -0
- package/src/index.ts +6 -0
- package/src/pages/directory-layout.tsx +88 -0
- package/src/pages/error.tsx +327 -0
- package/src/pages/home.tsx +131 -0
- package/src/pages/layout/deep-links.ts +50 -0
- package/src/pages/layout/helpers.test.ts +211 -0
- package/src/pages/layout/helpers.ts +98 -0
- package/src/pages/layout/inline-editor.tsx +126 -0
- package/src/pages/layout/sidebar-items.tsx +437 -0
- package/src/pages/layout/sidebar-project.tsx +384 -0
- package/src/pages/layout/sidebar-shell.tsx +125 -0
- package/src/pages/layout/sidebar-workspace.tsx +504 -0
- package/src/pages/layout.tsx +2509 -0
- package/src/pages/session/composer/index.ts +2 -0
- package/src/pages/session/composer/session-composer-region.tsx +255 -0
- package/src/pages/session/composer/session-composer-state.test.ts +128 -0
- package/src/pages/session/composer/session-composer-state.ts +249 -0
- package/src/pages/session/composer/session-followup-dock.tsx +109 -0
- package/src/pages/session/composer/session-permission-dock.tsx +74 -0
- package/src/pages/session/composer/session-question-dock.tsx +449 -0
- package/src/pages/session/composer/session-request-tree.ts +52 -0
- package/src/pages/session/composer/session-revert-dock.tsx +99 -0
- package/src/pages/session/composer/session-todo-dock.tsx +330 -0
- package/src/pages/session/file-tab-scroll.test.ts +40 -0
- package/src/pages/session/file-tab-scroll.ts +67 -0
- package/src/pages/session/file-tabs.tsx +456 -0
- package/src/pages/session/handoff.ts +36 -0
- package/src/pages/session/helpers.test.ts +181 -0
- package/src/pages/session/helpers.ts +198 -0
- package/src/pages/session/message-gesture.test.ts +62 -0
- package/src/pages/session/message-gesture.ts +21 -0
- package/src/pages/session/message-id-from-hash.ts +6 -0
- package/src/pages/session/message-timeline.tsx +1013 -0
- package/src/pages/session/review-tab.tsx +170 -0
- package/src/pages/session/session-layout.ts +20 -0
- package/src/pages/session/session-model-helpers.test.ts +51 -0
- package/src/pages/session/session-model-helpers.ts +16 -0
- package/src/pages/session/session-side-panel.tsx +453 -0
- package/src/pages/session/terminal-label.ts +16 -0
- package/src/pages/session/terminal-panel.test.ts +25 -0
- package/src/pages/session/terminal-panel.tsx +326 -0
- package/src/pages/session/use-session-commands.tsx +495 -0
- package/src/pages/session/use-session-hash-scroll.test.ts +16 -0
- package/src/pages/session/use-session-hash-scroll.ts +197 -0
- package/src/pages/session.tsx +1841 -0
- package/src/sst-env.d.ts +12 -0
- package/src/testing/model-selection.ts +80 -0
- package/src/testing/prompt.ts +56 -0
- package/src/testing/session-composer.ts +84 -0
- package/src/testing/terminal.ts +118 -0
- package/src/theme-preload.test.ts +46 -0
- package/src/utils/agent.ts +23 -0
- package/src/utils/aim.ts +138 -0
- package/src/utils/base64.ts +10 -0
- package/src/utils/comment-note.ts +88 -0
- package/src/utils/id.ts +99 -0
- package/src/utils/notification-click.test.ts +27 -0
- package/src/utils/notification-click.ts +13 -0
- package/src/utils/persist.test.ts +115 -0
- package/src/utils/persist.ts +476 -0
- package/src/utils/prompt.test.ts +44 -0
- package/src/utils/prompt.ts +203 -0
- package/src/utils/runtime-adapters.test.ts +62 -0
- package/src/utils/runtime-adapters.ts +39 -0
- package/src/utils/same.ts +6 -0
- package/src/utils/scoped-cache.test.ts +69 -0
- package/src/utils/scoped-cache.ts +104 -0
- package/src/utils/server-errors.test.ts +131 -0
- package/src/utils/server-errors.ts +80 -0
- package/src/utils/server-health.test.ts +123 -0
- package/src/utils/server-health.ts +91 -0
- package/src/utils/server.ts +22 -0
- package/src/utils/solid-dnd.tsx +49 -0
- package/src/utils/sound.ts +117 -0
- package/src/utils/terminal-writer.test.ts +64 -0
- package/src/utils/terminal-writer.ts +65 -0
- package/src/utils/time.ts +22 -0
- package/src/utils/uuid.test.ts +78 -0
- package/src/utils/uuid.ts +12 -0
- package/src/utils/worktree.test.ts +46 -0
- package/src/utils/worktree.ts +73 -0
- package/sst-env.d.ts +10 -0
- package/tsconfig.json +26 -0
- package/vite.config.ts +15 -0
- package/vite.js +26 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { serverNamePattern } from "../utils"
|
|
3
|
+
|
|
4
|
+
test("home renders and shows core entrypoints", async ({ page }) => {
|
|
5
|
+
await page.goto("/")
|
|
6
|
+
const nav = page.locator('[data-component="sidebar-nav-desktop"]')
|
|
7
|
+
|
|
8
|
+
await expect(page.getByRole("button", { name: "Open project" }).first()).toBeVisible()
|
|
9
|
+
await expect(nav.getByText("No projects open")).toBeVisible()
|
|
10
|
+
await expect(nav.getByText("Open a project to get started")).toBeVisible()
|
|
11
|
+
await expect(page.getByRole("button", { name: serverNamePattern })).toBeVisible()
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test("server picker dialog opens from home", async ({ page }) => {
|
|
15
|
+
await page.goto("/")
|
|
16
|
+
|
|
17
|
+
const trigger = page.getByRole("button", { name: serverNamePattern })
|
|
18
|
+
await expect(trigger).toBeVisible()
|
|
19
|
+
await trigger.click()
|
|
20
|
+
|
|
21
|
+
const dialog = page.getByRole("dialog")
|
|
22
|
+
await expect(dialog).toBeVisible()
|
|
23
|
+
await expect(dialog.getByRole("textbox").first()).toBeVisible()
|
|
24
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
import { dirPath } from "../utils"
|
|
4
|
+
|
|
5
|
+
test("project route redirects to /session", async ({ page, directory, slug }) => {
|
|
6
|
+
await page.goto(dirPath(directory))
|
|
7
|
+
|
|
8
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session`))
|
|
9
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
10
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { closeDialog, openPalette } from "../actions"
|
|
3
|
+
|
|
4
|
+
test("search palette opens and closes", async ({ page, gotoSession }) => {
|
|
5
|
+
await gotoSession()
|
|
6
|
+
|
|
7
|
+
const dialog = await openPalette(page)
|
|
8
|
+
|
|
9
|
+
await page.keyboard.press("Escape")
|
|
10
|
+
await expect(dialog).toHaveCount(0)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test("search palette also opens with cmd+p", async ({ page, gotoSession }) => {
|
|
14
|
+
await gotoSession()
|
|
15
|
+
|
|
16
|
+
const dialog = await openPalette(page, "P")
|
|
17
|
+
|
|
18
|
+
await closeDialog(page, dialog)
|
|
19
|
+
await expect(dialog).toHaveCount(0)
|
|
20
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { serverNamePattern, serverUrls } from "../utils"
|
|
3
|
+
import { closeDialog, clickMenuItem } from "../actions"
|
|
4
|
+
|
|
5
|
+
const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl"
|
|
6
|
+
|
|
7
|
+
test("can set a default server on web", async ({ page, gotoSession }) => {
|
|
8
|
+
await page.addInitScript((key: string) => {
|
|
9
|
+
try {
|
|
10
|
+
localStorage.removeItem(key)
|
|
11
|
+
} catch {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
}, DEFAULT_SERVER_URL_KEY)
|
|
15
|
+
|
|
16
|
+
await gotoSession()
|
|
17
|
+
|
|
18
|
+
const status = page.getByRole("button", { name: "Status" })
|
|
19
|
+
await expect(status).toBeVisible()
|
|
20
|
+
const popover = page.locator('[data-component="popover-content"]').filter({ hasText: "Manage servers" })
|
|
21
|
+
|
|
22
|
+
const ensurePopoverOpen = async () => {
|
|
23
|
+
if (await popover.isVisible()) return
|
|
24
|
+
await status.click()
|
|
25
|
+
await expect(popover).toBeVisible()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await ensurePopoverOpen()
|
|
29
|
+
await popover.getByRole("button", { name: "Manage servers" }).click()
|
|
30
|
+
|
|
31
|
+
const dialog = page.getByRole("dialog")
|
|
32
|
+
await expect(dialog).toBeVisible()
|
|
33
|
+
|
|
34
|
+
await expect(dialog.getByText(serverNamePattern).first()).toBeVisible()
|
|
35
|
+
|
|
36
|
+
const menuTrigger = dialog.locator('[data-slot="dropdown-menu-trigger"]').first()
|
|
37
|
+
await expect(menuTrigger).toBeVisible()
|
|
38
|
+
await menuTrigger.click({ force: true })
|
|
39
|
+
|
|
40
|
+
const menu = page.locator('[data-component="dropdown-menu-content"]').first()
|
|
41
|
+
await expect(menu).toBeVisible()
|
|
42
|
+
await clickMenuItem(menu, /set as default/i)
|
|
43
|
+
|
|
44
|
+
await expect
|
|
45
|
+
.poll(async () =>
|
|
46
|
+
serverUrls.includes((await page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)) ?? ""),
|
|
47
|
+
)
|
|
48
|
+
.toBe(true)
|
|
49
|
+
await expect(dialog.getByText("Default", { exact: true })).toBeVisible()
|
|
50
|
+
|
|
51
|
+
await closeDialog(page, dialog)
|
|
52
|
+
|
|
53
|
+
await ensurePopoverOpen()
|
|
54
|
+
|
|
55
|
+
const serverRow = popover.locator("button").filter({ hasText: serverNamePattern }).first()
|
|
56
|
+
await expect(serverRow).toBeVisible()
|
|
57
|
+
await expect(serverRow.getByText("Default", { exact: true })).toBeVisible()
|
|
58
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
import { withSession } from "../actions"
|
|
4
|
+
|
|
5
|
+
test("can open an existing session and type into the prompt", async ({ page, sdk, gotoSession }) => {
|
|
6
|
+
const title = `e2e smoke ${Date.now()}`
|
|
7
|
+
|
|
8
|
+
await withSession(sdk, title, async (session) => {
|
|
9
|
+
await gotoSession(session.id)
|
|
10
|
+
|
|
11
|
+
const prompt = page.locator(promptSelector)
|
|
12
|
+
await prompt.click()
|
|
13
|
+
await page.keyboard.type("hello from e2e")
|
|
14
|
+
await expect(prompt).toContainText("hello from e2e")
|
|
15
|
+
})
|
|
16
|
+
})
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { defocus, openSidebar, withSession } from "../actions"
|
|
3
|
+
import { promptSelector } from "../selectors"
|
|
4
|
+
import { modKey } from "../utils"
|
|
5
|
+
|
|
6
|
+
test("titlebar back/forward navigates between sessions", async ({ page, slug, sdk, gotoSession }) => {
|
|
7
|
+
await page.setViewportSize({ width: 1400, height: 800 })
|
|
8
|
+
|
|
9
|
+
const stamp = Date.now()
|
|
10
|
+
|
|
11
|
+
await withSession(sdk, `e2e titlebar history 1 ${stamp}`, async (one) => {
|
|
12
|
+
await withSession(sdk, `e2e titlebar history 2 ${stamp}`, async (two) => {
|
|
13
|
+
await gotoSession(one.id)
|
|
14
|
+
|
|
15
|
+
await openSidebar(page)
|
|
16
|
+
|
|
17
|
+
const link = page.locator(`[data-session-id="${two.id}"] a`).first()
|
|
18
|
+
await expect(link).toBeVisible()
|
|
19
|
+
await link.click()
|
|
20
|
+
|
|
21
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`))
|
|
22
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
23
|
+
|
|
24
|
+
const back = page.getByRole("button", { name: "Back" })
|
|
25
|
+
const forward = page.getByRole("button", { name: "Forward" })
|
|
26
|
+
|
|
27
|
+
await expect(back).toBeVisible()
|
|
28
|
+
await expect(back).toBeEnabled()
|
|
29
|
+
await back.click()
|
|
30
|
+
|
|
31
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${one.id}(?:\\?|#|$)`))
|
|
32
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
33
|
+
|
|
34
|
+
await expect(forward).toBeVisible()
|
|
35
|
+
await expect(forward).toBeEnabled()
|
|
36
|
+
await forward.click()
|
|
37
|
+
|
|
38
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`))
|
|
39
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test("titlebar forward is cleared after branching history from sidebar", async ({ page, slug, sdk, gotoSession }) => {
|
|
45
|
+
await page.setViewportSize({ width: 1400, height: 800 })
|
|
46
|
+
|
|
47
|
+
const stamp = Date.now()
|
|
48
|
+
|
|
49
|
+
await withSession(sdk, `e2e titlebar history a ${stamp}`, async (a) => {
|
|
50
|
+
await withSession(sdk, `e2e titlebar history b ${stamp}`, async (b) => {
|
|
51
|
+
await withSession(sdk, `e2e titlebar history c ${stamp}`, async (c) => {
|
|
52
|
+
await gotoSession(a.id)
|
|
53
|
+
|
|
54
|
+
await openSidebar(page)
|
|
55
|
+
|
|
56
|
+
const second = page.locator(`[data-session-id="${b.id}"] a`).first()
|
|
57
|
+
await expect(second).toBeVisible()
|
|
58
|
+
await second.click()
|
|
59
|
+
|
|
60
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${b.id}(?:\\?|#|$)`))
|
|
61
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
62
|
+
|
|
63
|
+
const back = page.getByRole("button", { name: "Back" })
|
|
64
|
+
const forward = page.getByRole("button", { name: "Forward" })
|
|
65
|
+
|
|
66
|
+
await expect(back).toBeVisible()
|
|
67
|
+
await expect(back).toBeEnabled()
|
|
68
|
+
await back.click()
|
|
69
|
+
|
|
70
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${a.id}(?:\\?|#|$)`))
|
|
71
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
72
|
+
|
|
73
|
+
await openSidebar(page)
|
|
74
|
+
|
|
75
|
+
const third = page.locator(`[data-session-id="${c.id}"] a`).first()
|
|
76
|
+
await expect(third).toBeVisible()
|
|
77
|
+
await third.click()
|
|
78
|
+
|
|
79
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${c.id}(?:\\?|#|$)`))
|
|
80
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
81
|
+
|
|
82
|
+
await expect(forward).toBeVisible()
|
|
83
|
+
await expect(forward).toBeDisabled()
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
test("keyboard shortcuts navigate titlebar history", async ({ page, slug, sdk, gotoSession }) => {
|
|
90
|
+
await page.setViewportSize({ width: 1400, height: 800 })
|
|
91
|
+
|
|
92
|
+
const stamp = Date.now()
|
|
93
|
+
|
|
94
|
+
await withSession(sdk, `e2e titlebar shortcuts 1 ${stamp}`, async (one) => {
|
|
95
|
+
await withSession(sdk, `e2e titlebar shortcuts 2 ${stamp}`, async (two) => {
|
|
96
|
+
await gotoSession(one.id)
|
|
97
|
+
|
|
98
|
+
await openSidebar(page)
|
|
99
|
+
|
|
100
|
+
const link = page.locator(`[data-session-id="${two.id}"] a`).first()
|
|
101
|
+
await expect(link).toBeVisible()
|
|
102
|
+
await link.click()
|
|
103
|
+
|
|
104
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`))
|
|
105
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
106
|
+
|
|
107
|
+
await defocus(page)
|
|
108
|
+
await page.keyboard.press(`${modKey}+[`)
|
|
109
|
+
|
|
110
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${one.id}(?:\\?|#|$)`))
|
|
111
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
112
|
+
|
|
113
|
+
await defocus(page)
|
|
114
|
+
await page.keyboard.press(`${modKey}+]`)
|
|
115
|
+
|
|
116
|
+
await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`))
|
|
117
|
+
await expect(page.locator(promptSelector)).toBeVisible()
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
|
|
4
|
+
test("ctrl+l focuses the prompt", async ({ page, gotoSession }) => {
|
|
5
|
+
await gotoSession()
|
|
6
|
+
|
|
7
|
+
const prompt = page.locator(promptSelector)
|
|
8
|
+
await expect(prompt).toBeVisible()
|
|
9
|
+
|
|
10
|
+
await page.locator("main").click({ position: { x: 5, y: 5 } })
|
|
11
|
+
await expect(prompt).not.toBeFocused()
|
|
12
|
+
|
|
13
|
+
await page.keyboard.press("Control+L")
|
|
14
|
+
await expect(prompt).toBeFocused()
|
|
15
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { modKey } from "../utils"
|
|
3
|
+
|
|
4
|
+
const expanded = async (el: { getAttribute: (name: string) => Promise<string | null> }) => {
|
|
5
|
+
const value = await el.getAttribute("aria-expanded")
|
|
6
|
+
if (value !== "true" && value !== "false") throw new Error(`Expected aria-expanded to be true|false, got: ${value}`)
|
|
7
|
+
return value === "true"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
test("review panel can be toggled via keybind", async ({ page, gotoSession }) => {
|
|
11
|
+
await gotoSession()
|
|
12
|
+
|
|
13
|
+
const reviewPanel = page.locator("#review-panel")
|
|
14
|
+
|
|
15
|
+
const treeToggle = page.getByRole("button", { name: "Toggle file tree" }).first()
|
|
16
|
+
await expect(treeToggle).toBeVisible()
|
|
17
|
+
if (await expanded(treeToggle)) await treeToggle.click()
|
|
18
|
+
await expect(treeToggle).toHaveAttribute("aria-expanded", "false")
|
|
19
|
+
|
|
20
|
+
const reviewToggle = page.getByRole("button", { name: "Toggle review" }).first()
|
|
21
|
+
await expect(reviewToggle).toBeVisible()
|
|
22
|
+
if (await expanded(reviewToggle)) await reviewToggle.click()
|
|
23
|
+
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
|
24
|
+
await expect(reviewPanel).toHaveAttribute("aria-hidden", "true")
|
|
25
|
+
|
|
26
|
+
await page.keyboard.press(`${modKey}+Shift+R`)
|
|
27
|
+
await expect(reviewToggle).toHaveAttribute("aria-expanded", "true")
|
|
28
|
+
await expect(reviewPanel).toHaveAttribute("aria-hidden", "false")
|
|
29
|
+
|
|
30
|
+
await page.keyboard.press(`${modKey}+Shift+R`)
|
|
31
|
+
await expect(reviewToggle).toHaveAttribute("aria-expanded", "false")
|
|
32
|
+
await expect(reviewPanel).toHaveAttribute("aria-hidden", "true")
|
|
33
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
import { modKey } from "../utils"
|
|
4
|
+
|
|
5
|
+
test("mod+w closes the active file tab", async ({ page, gotoSession }) => {
|
|
6
|
+
await gotoSession()
|
|
7
|
+
|
|
8
|
+
await page.locator(promptSelector).click()
|
|
9
|
+
await page.keyboard.type("/open")
|
|
10
|
+
await expect(page.locator('[data-slash-id="file.open"]').first()).toBeVisible()
|
|
11
|
+
await page.keyboard.press("Enter")
|
|
12
|
+
|
|
13
|
+
const dialog = page
|
|
14
|
+
.getByRole("dialog")
|
|
15
|
+
.filter({ has: page.getByPlaceholder(/search files/i) })
|
|
16
|
+
.first()
|
|
17
|
+
await expect(dialog).toBeVisible()
|
|
18
|
+
|
|
19
|
+
await dialog.getByRole("textbox").first().fill("package.json")
|
|
20
|
+
const item = dialog.locator('[data-slot="list-item"][data-key^="file:"]').first()
|
|
21
|
+
await expect(item).toBeVisible({ timeout: 30_000 })
|
|
22
|
+
await item.click()
|
|
23
|
+
await expect(dialog).toHaveCount(0)
|
|
24
|
+
|
|
25
|
+
const tab = page.getByRole("tab", { name: "package.json" }).first()
|
|
26
|
+
await expect(tab).toBeVisible()
|
|
27
|
+
await tab.click()
|
|
28
|
+
await expect(tab).toHaveAttribute("aria-selected", "true")
|
|
29
|
+
|
|
30
|
+
await page.keyboard.press(`${modKey}+W`)
|
|
31
|
+
await expect(page.getByRole("tab", { name: "package.json" })).toHaveCount(0)
|
|
32
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
|
|
4
|
+
test("can open a file tab from the search palette", async ({ page, gotoSession }) => {
|
|
5
|
+
await gotoSession()
|
|
6
|
+
|
|
7
|
+
await page.locator(promptSelector).click()
|
|
8
|
+
await page.keyboard.type("/open")
|
|
9
|
+
|
|
10
|
+
const command = page.locator('[data-slash-id="file.open"]').first()
|
|
11
|
+
await expect(command).toBeVisible()
|
|
12
|
+
await page.keyboard.press("Enter")
|
|
13
|
+
|
|
14
|
+
const dialog = page
|
|
15
|
+
.getByRole("dialog")
|
|
16
|
+
.filter({ has: page.getByPlaceholder(/search files/i) })
|
|
17
|
+
.first()
|
|
18
|
+
await expect(dialog).toBeVisible()
|
|
19
|
+
|
|
20
|
+
const input = dialog.getByRole("textbox").first()
|
|
21
|
+
await input.fill("package.json")
|
|
22
|
+
|
|
23
|
+
const item = dialog.locator('[data-slot="list-item"][data-key^="file:"]').first()
|
|
24
|
+
await expect(item).toBeVisible({ timeout: 30_000 })
|
|
25
|
+
await item.click()
|
|
26
|
+
|
|
27
|
+
await expect(dialog).toHaveCount(0)
|
|
28
|
+
|
|
29
|
+
const tabs = page.locator('[data-component="tabs"][data-variant="normal"]')
|
|
30
|
+
await expect(tabs.locator('[data-slot="tabs-trigger"]').first()).toBeVisible()
|
|
31
|
+
})
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
|
|
3
|
+
test("file tree can expand folders and open a file", async ({ page, gotoSession }) => {
|
|
4
|
+
await gotoSession()
|
|
5
|
+
|
|
6
|
+
const toggle = page.getByRole("button", { name: "Toggle file tree" })
|
|
7
|
+
const panel = page.locator("#file-tree-panel")
|
|
8
|
+
const treeTabs = panel.locator('[data-component="tabs"][data-variant="pill"][data-scope="filetree"]')
|
|
9
|
+
|
|
10
|
+
await expect(toggle).toBeVisible()
|
|
11
|
+
if ((await toggle.getAttribute("aria-expanded")) !== "true") await toggle.click()
|
|
12
|
+
await expect(toggle).toHaveAttribute("aria-expanded", "true")
|
|
13
|
+
await expect(panel).toBeVisible()
|
|
14
|
+
await expect(treeTabs).toBeVisible()
|
|
15
|
+
|
|
16
|
+
const allTab = treeTabs.getByRole("tab", { name: /^all files$/i })
|
|
17
|
+
await expect(allTab).toBeVisible()
|
|
18
|
+
await allTab.click()
|
|
19
|
+
await expect(allTab).toHaveAttribute("aria-selected", "true")
|
|
20
|
+
|
|
21
|
+
const tree = treeTabs.locator('[data-slot="tabs-content"]:not([hidden])')
|
|
22
|
+
await expect(tree).toBeVisible()
|
|
23
|
+
|
|
24
|
+
const expand = async (name: string) => {
|
|
25
|
+
const folder = tree.getByRole("button", { name, exact: true }).first()
|
|
26
|
+
await expect(folder).toBeVisible()
|
|
27
|
+
await expect(folder).toHaveAttribute("aria-expanded", /true|false/)
|
|
28
|
+
if ((await folder.getAttribute("aria-expanded")) === "false") await folder.click()
|
|
29
|
+
await expect(folder).toHaveAttribute("aria-expanded", "true")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
await expand("packages")
|
|
33
|
+
await expand("app")
|
|
34
|
+
await expand("src")
|
|
35
|
+
await expand("components")
|
|
36
|
+
|
|
37
|
+
const file = tree.getByRole("button", { name: "file-tree.tsx", exact: true }).first()
|
|
38
|
+
await expect(file).toBeVisible()
|
|
39
|
+
await file.click()
|
|
40
|
+
|
|
41
|
+
const tab = page.getByRole("tab", { name: "file-tree.tsx" })
|
|
42
|
+
await expect(tab).toBeVisible()
|
|
43
|
+
await tab.click()
|
|
44
|
+
await expect(tab).toHaveAttribute("aria-selected", "true")
|
|
45
|
+
|
|
46
|
+
await toggle.click()
|
|
47
|
+
await expect(toggle).toHaveAttribute("aria-expanded", "false")
|
|
48
|
+
|
|
49
|
+
await toggle.click()
|
|
50
|
+
await expect(toggle).toHaveAttribute("aria-expanded", "true")
|
|
51
|
+
await expect(allTab).toHaveAttribute("aria-selected", "true")
|
|
52
|
+
|
|
53
|
+
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
|
54
|
+
await expect(viewer).toBeVisible()
|
|
55
|
+
await expect(viewer).toContainText("export default function FileTree")
|
|
56
|
+
})
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { test, expect } from "../fixtures"
|
|
2
|
+
import { promptSelector } from "../selectors"
|
|
3
|
+
import { modKey } from "../utils"
|
|
4
|
+
|
|
5
|
+
test("smoke file viewer renders real file content", async ({ page, gotoSession }) => {
|
|
6
|
+
await gotoSession()
|
|
7
|
+
|
|
8
|
+
await page.locator(promptSelector).click()
|
|
9
|
+
await page.keyboard.type("/open")
|
|
10
|
+
|
|
11
|
+
const command = page.locator('[data-slash-id="file.open"]').first()
|
|
12
|
+
await expect(command).toBeVisible()
|
|
13
|
+
await page.keyboard.press("Enter")
|
|
14
|
+
|
|
15
|
+
const dialog = page
|
|
16
|
+
.getByRole("dialog")
|
|
17
|
+
.filter({ has: page.getByPlaceholder(/search files/i) })
|
|
18
|
+
.first()
|
|
19
|
+
await expect(dialog).toBeVisible()
|
|
20
|
+
|
|
21
|
+
const input = dialog.getByRole("textbox").first()
|
|
22
|
+
await input.fill("package.json")
|
|
23
|
+
|
|
24
|
+
const items = dialog.locator('[data-slot="list-item"][data-key^="file:"]')
|
|
25
|
+
let index = -1
|
|
26
|
+
await expect
|
|
27
|
+
.poll(
|
|
28
|
+
async () => {
|
|
29
|
+
const keys = await items.evaluateAll((nodes) => nodes.map((node) => node.getAttribute("data-key") ?? ""))
|
|
30
|
+
index = keys.findIndex((key) => /packages[\\/]+app[\\/]+package\.json$/i.test(key.replace(/^file:/, "")))
|
|
31
|
+
return index >= 0
|
|
32
|
+
},
|
|
33
|
+
{ timeout: 30_000 },
|
|
34
|
+
)
|
|
35
|
+
.toBe(true)
|
|
36
|
+
|
|
37
|
+
const item = items.nth(index)
|
|
38
|
+
await expect(item).toBeVisible()
|
|
39
|
+
await item.click()
|
|
40
|
+
|
|
41
|
+
await expect(dialog).toHaveCount(0)
|
|
42
|
+
|
|
43
|
+
const tab = page.getByRole("tab", { name: "package.json" })
|
|
44
|
+
await expect(tab).toBeVisible()
|
|
45
|
+
await tab.click()
|
|
46
|
+
|
|
47
|
+
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
|
48
|
+
await expect(viewer).toBeVisible()
|
|
49
|
+
await expect(viewer.getByText(/"name"\s*:\s*"@reign-labs\/app"/)).toBeVisible()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test("cmd+f opens text viewer search while prompt is focused", async ({ page, gotoSession }) => {
|
|
53
|
+
await gotoSession()
|
|
54
|
+
|
|
55
|
+
await page.locator(promptSelector).click()
|
|
56
|
+
await page.keyboard.type("/open")
|
|
57
|
+
|
|
58
|
+
const command = page.locator('[data-slash-id="file.open"]').first()
|
|
59
|
+
await expect(command).toBeVisible()
|
|
60
|
+
await page.keyboard.press("Enter")
|
|
61
|
+
|
|
62
|
+
const dialog = page
|
|
63
|
+
.getByRole("dialog")
|
|
64
|
+
.filter({ has: page.getByPlaceholder(/search files/i) })
|
|
65
|
+
.first()
|
|
66
|
+
await expect(dialog).toBeVisible()
|
|
67
|
+
|
|
68
|
+
const input = dialog.getByRole("textbox").first()
|
|
69
|
+
await input.fill("package.json")
|
|
70
|
+
|
|
71
|
+
const items = dialog.locator('[data-slot="list-item"][data-key^="file:"]')
|
|
72
|
+
let index = -1
|
|
73
|
+
await expect
|
|
74
|
+
.poll(
|
|
75
|
+
async () => {
|
|
76
|
+
const keys = await items.evaluateAll((nodes) => nodes.map((node) => node.getAttribute("data-key") ?? ""))
|
|
77
|
+
index = keys.findIndex((key) => /packages[\\/]+app[\\/]+package\.json$/i.test(key.replace(/^file:/, "")))
|
|
78
|
+
return index >= 0
|
|
79
|
+
},
|
|
80
|
+
{ timeout: 30_000 },
|
|
81
|
+
)
|
|
82
|
+
.toBe(true)
|
|
83
|
+
|
|
84
|
+
const item = items.nth(index)
|
|
85
|
+
await expect(item).toBeVisible()
|
|
86
|
+
await item.click()
|
|
87
|
+
|
|
88
|
+
await expect(dialog).toHaveCount(0)
|
|
89
|
+
|
|
90
|
+
const tab = page.getByRole("tab", { name: "package.json" })
|
|
91
|
+
await expect(tab).toBeVisible()
|
|
92
|
+
await tab.click()
|
|
93
|
+
|
|
94
|
+
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
|
95
|
+
await expect(viewer).toBeVisible()
|
|
96
|
+
|
|
97
|
+
await page.locator(promptSelector).click()
|
|
98
|
+
await page.keyboard.press(`${modKey}+f`)
|
|
99
|
+
|
|
100
|
+
const findInput = page.getByPlaceholder("Find")
|
|
101
|
+
await expect(findInput).toBeVisible()
|
|
102
|
+
await expect(findInput).toBeFocused()
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test("cmd+f opens text viewer search while prompt is not focused", async ({ page, gotoSession }) => {
|
|
106
|
+
await gotoSession()
|
|
107
|
+
|
|
108
|
+
await page.locator(promptSelector).click()
|
|
109
|
+
await page.keyboard.type("/open")
|
|
110
|
+
|
|
111
|
+
const command = page.locator('[data-slash-id="file.open"]').first()
|
|
112
|
+
await expect(command).toBeVisible()
|
|
113
|
+
await page.keyboard.press("Enter")
|
|
114
|
+
|
|
115
|
+
const dialog = page
|
|
116
|
+
.getByRole("dialog")
|
|
117
|
+
.filter({ has: page.getByPlaceholder(/search files/i) })
|
|
118
|
+
.first()
|
|
119
|
+
await expect(dialog).toBeVisible()
|
|
120
|
+
|
|
121
|
+
const input = dialog.getByRole("textbox").first()
|
|
122
|
+
await input.fill("package.json")
|
|
123
|
+
|
|
124
|
+
const items = dialog.locator('[data-slot="list-item"][data-key^="file:"]')
|
|
125
|
+
let index = -1
|
|
126
|
+
await expect
|
|
127
|
+
.poll(
|
|
128
|
+
async () => {
|
|
129
|
+
const keys = await items.evaluateAll((nodes) => nodes.map((node) => node.getAttribute("data-key") ?? ""))
|
|
130
|
+
index = keys.findIndex((key) => /packages[\\/]+app[\\/]+package\.json$/i.test(key.replace(/^file:/, "")))
|
|
131
|
+
return index >= 0
|
|
132
|
+
},
|
|
133
|
+
{ timeout: 30_000 },
|
|
134
|
+
)
|
|
135
|
+
.toBe(true)
|
|
136
|
+
|
|
137
|
+
const item = items.nth(index)
|
|
138
|
+
await expect(item).toBeVisible()
|
|
139
|
+
await item.click()
|
|
140
|
+
|
|
141
|
+
await expect(dialog).toHaveCount(0)
|
|
142
|
+
|
|
143
|
+
const tab = page.getByRole("tab", { name: "package.json" })
|
|
144
|
+
await expect(tab).toBeVisible()
|
|
145
|
+
await tab.click()
|
|
146
|
+
|
|
147
|
+
const viewer = page.locator('[data-component="file"][data-mode="text"]').first()
|
|
148
|
+
await expect(viewer).toBeVisible()
|
|
149
|
+
|
|
150
|
+
await viewer.click()
|
|
151
|
+
await page.keyboard.press(`${modKey}+f`)
|
|
152
|
+
|
|
153
|
+
const findInput = page.getByPlaceholder("Find")
|
|
154
|
+
await expect(findInput).toBeVisible()
|
|
155
|
+
await expect(findInput).toBeFocused()
|
|
156
|
+
})
|