Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/accessibility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ authTest.describe("Accessibility: page editor", () => {
// Empty workspace — that's fine, we'll create a page
}

const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
await newPageBtn.waitFor({ state: "visible", timeout: 10_000 });
await newPageBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-add-property-types.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-bulk-select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-crud.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-csv-export.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-duplicate-row.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-duplicate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-error-recovery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-filter-keyboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-filter-types.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
4 changes: 2 additions & 2 deletions e2e/database-inline.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function waitForSidebarTree(page: Page) {
async function createDatabaseFromSidebar(page: Page): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down Expand Up @@ -87,7 +87,7 @@ async function addRowToDatabase(page: Page) {
async function navigateToNewPage(page: Page): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
await expect(newPageBtn).toBeVisible({ timeout: 5_000 });
await newPageBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-row-page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function createDatabaseWithRow(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-table-editor-portal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-table-keyboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/database-views.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function createDatabaseFromSidebar(
): Promise<string> {
const sidebar = await waitForSidebarTree(page);

const newDbBtn = sidebar.getByRole("button", { name: /new database/i });
const newDbBtn = sidebar.getByTestId("sb-new-database-btn");
await expect(newDbBtn).toBeVisible({ timeout: 5_000 });
await newDbBtn.click();

Expand Down
2 changes: 1 addition & 1 deletion e2e/favorites.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test.describe("Sidebar Favorites", () => {
title: string,
): Promise<string> {
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
await newPageBtn.click();

await page.waitForURL(
Expand Down
4 changes: 2 additions & 2 deletions e2e/mobile-responsive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ test.describe("Mobile viewport responsive behavior", () => {
await page.setViewportSize(MOBILE_VIEWPORT);

// Open the mobile sidebar sheet
const toggleButton = page.getByRole("button", { name: "Toggle sidebar" });
const toggleButton = page.getByTestId("as-sidebar-toggle");
await expect(toggleButton).toBeVisible({ timeout: 10_000 });
await toggleButton.click();

Expand All @@ -250,7 +250,7 @@ test.describe("Mobile viewport responsive behavior", () => {
await expect(treeLoaded).toBeVisible({ timeout: 10_000 });

// Create a new page via the sidebar
const newPageBtn = sheetContent.getByRole("button", { name: /new page/i });
const newPageBtn = sheetContent.getByTestId("sb-new-page-btn");
await expect(newPageBtn).toBeVisible({ timeout: 5_000 });
await newPageBtn.click();

Expand Down
4 changes: 2 additions & 2 deletions e2e/page-crud.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ test.describe("Page CRUD", () => {
// Tree loaded but empty — that's fine
}

const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found");
return;
Expand Down Expand Up @@ -138,7 +138,7 @@ test.describe("Page CRUD", () => {
}

// Create a page first so we have something to delete
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found");
return;
Expand Down
10 changes: 5 additions & 5 deletions e2e/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async function createPageWithTitle(
title: string
): Promise<string> {
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
await newPageBtn.click();

await page.waitForURL(
Expand Down Expand Up @@ -84,7 +84,7 @@ test.describe("Sidebar search", () => {
authenticatedPage: page,
}) => {
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found — cannot set up search test");
return;
Expand All @@ -99,7 +99,7 @@ test.describe("Sidebar search", () => {
}) => {
// First create a page so we have something to search for
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found");
return;
Expand Down Expand Up @@ -135,7 +135,7 @@ test.describe("Sidebar search", () => {
}) => {
// Create a page to search for
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found");
return;
Expand Down Expand Up @@ -213,7 +213,7 @@ test.describe("Sidebar search", () => {
}) => {
// Create a page in the current workspace with a unique identifier
const sidebar = page.getByRole("complementary");
const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) === 0) {
test.skip(true, "New page button not found");
return;
Expand Down
8 changes: 4 additions & 4 deletions e2e/sidebar-responsive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test.describe("Responsive sidebar behavior", () => {
await expect(sheetContent).toBeHidden();

// Mobile header with hamburger button should be visible
const toggleButton = page.getByRole("button", { name: "Toggle sidebar" });
const toggleButton = page.getByTestId("as-sidebar-toggle");
await expect(toggleButton).toBeVisible({ timeout: 5_000 });

// Click the hamburger to open the Sheet sidebar
Expand Down Expand Up @@ -53,7 +53,7 @@ test.describe("Responsive sidebar behavior", () => {
expect(box!.width).toBeGreaterThan(0);

// The mobile hamburger toggle should NOT be visible on desktop
const toggleButton = page.getByRole("button", { name: "Toggle sidebar" });
const toggleButton = page.getByTestId("as-sidebar-toggle");
await expect(toggleButton).toBeHidden();

// Sheet overlay should not be present
Expand Down Expand Up @@ -104,7 +104,7 @@ test.describe("Responsive sidebar behavior", () => {
await expect(sheetContent).toBeHidden();

// Open the sidebar Sheet
const toggleButton = page.getByRole("button", { name: "Toggle sidebar" });
const toggleButton = page.getByTestId("as-sidebar-toggle");
await expect(toggleButton).toBeVisible({ timeout: 5_000 });
await toggleButton.click();
await expect(sheetContent).toBeVisible({ timeout: 5_000 });
Expand All @@ -115,7 +115,7 @@ test.describe("Responsive sidebar behavior", () => {
await expect(treeItem).toBeVisible({ timeout: 10_000 });
} catch {
// No pages exist — create one so we can navigate
const newPageBtn = sheetContent.getByRole("button", { name: /new page/i });
const newPageBtn = sheetContent.getByTestId("sb-new-page-btn");
if ((await newPageBtn.count()) > 0) {
await newPageBtn.click();
// Wait for navigation to the new page
Expand Down
2 changes: 1 addition & 1 deletion e2e/trash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async function createPage(page: import("@playwright/test").Page) {
const sidebar = page.getByRole("complementary");
await waitForTreeLoaded(page);

const newPageBtn = sidebar.getByRole("button", { name: /new page/i });
const newPageBtn = sidebar.getByTestId("sb-new-page-btn");
await newPageBtn.click();

// Wait for navigation to the new page
Expand Down
15 changes: 6 additions & 9 deletions e2e/workspace-home-mobile-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,12 @@ test.describe("Workspace home — mobile header layout", () => {
await page.goto("/");
const main = page.locator("#main-content");

// Wait for the workspace home to load — look for a heading
const heading = main.locator("h1").first();
await expect(heading).toBeVisible({ timeout: 15_000 });

// Scope to the header row (the container that holds the h1) to avoid
// matching sidebar page buttons like "Untitled Database just now".
const headerRow = heading.locator("..");
const dbButton = headerRow.getByRole("button", { name: /database/i });
const pageButton = headerRow.getByRole("button", { name: /page/i });
// Wait for the workspace home to load — look for the header
const header = main.getByTestId("wh-header");
await expect(header).toBeVisible({ timeout: 15_000 });

const dbButton = main.getByTestId("wh-new-database-btn");
const pageButton = main.getByTestId("wh-new-page-btn");
await expect(dbButton).toBeVisible({ timeout: 5_000 });
await expect(pageButton).toBeVisible({ timeout: 5_000 });

Expand Down
2 changes: 1 addition & 1 deletion e2e/workspace-home-new-database.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ test.describe("Workspace home — New Database button", () => {
const main = page.locator("#main-content");

// Wait for the workspace home page to load (the heading and buttons)
const newDbButton = main.getByRole("button", { name: /new database/i });
const newDbButton = main.getByTestId("wh-new-database-btn");
await expect(newDbButton).toBeVisible({ timeout: 15_000 });

// Click the "New Database" button
Expand Down
19 changes: 7 additions & 12 deletions e2e/workspace-home.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import { test, expect } from "./fixtures/auth";
import type { Locator } from "@playwright/test";

/**
* Returns the "All Pages" container — the div.mt-6 that holds the heading,
* filter/sort toolbar, and the page list.
* Returns the "All Pages" container using its data-testid attribute.
*/
function getAllPagesSection(main: Locator): Locator {
// The "All Pages" heading is inside a div.mt-6. Use the filter input's
// ancestor to scope precisely — the filter input only exists in "All Pages".
return main.locator("div.mt-6").filter({
hasText: /All Pages/,
});
return main.locator('[data-testid="wh-all-pages"]');
}

/**
Expand Down Expand Up @@ -42,7 +37,7 @@ async function collectTitles(
* Waits for the workspace home page to fully load inside #main-content.
*/
async function waitForWorkspaceHome(main: Locator): Promise<void> {
const filterInput = main.getByRole("textbox", { name: /filter pages/i });
const filterInput = main.getByTestId("wh-filter-input");
await expect(filterInput).toBeVisible({ timeout: 15_000 });
}

Expand All @@ -52,7 +47,7 @@ test.describe("Workspace home page interactions", () => {
}) => {
const main = page.locator("#main-content");

const newPageButton = main.getByRole("button", { name: /new page/i });
const newPageButton = main.getByTestId("wh-new-page-btn");
await expect(newPageButton).toBeVisible({ timeout: 15_000 });

await newPageButton.click();
Expand All @@ -76,7 +71,7 @@ test.describe("Workspace home page interactions", () => {
const main = page.locator("#main-content");
await waitForWorkspaceHome(main);

const filterInput = main.getByRole("textbox", { name: /filter pages/i });
const filterInput = main.getByTestId("wh-filter-input");
const pageItems = getPageListItems(main);

await expect(pageItems.first()).toBeVisible({ timeout: 10_000 });
Expand Down Expand Up @@ -130,7 +125,7 @@ test.describe("Workspace home page interactions", () => {
const main = page.locator("#main-content");
await waitForWorkspaceHome(main);

const sortTrigger = main.getByRole("combobox", { name: /sort pages/i });
const sortTrigger = main.getByTestId("wh-sort-dropdown");
const pageItems = getPageListItems(main);

await expect(pageItems.first()).toBeVisible({ timeout: 10_000 });
Expand Down Expand Up @@ -231,7 +226,7 @@ test.describe("Workspace home page interactions", () => {
const main = page.locator("#main-content");
await waitForWorkspaceHome(main);

const filterInput = main.getByRole("textbox", { name: /filter pages/i });
const filterInput = main.getByTestId("wh-filter-input");
const pageItems = getPageListItems(main);

await expect(pageItems.first()).toBeVisible({ timeout: 10_000 });
Expand Down
2 changes: 1 addition & 1 deletion src/components/sidebar/app-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function AppShellInner({
children,
}: AppShellProps) {
return (
<div className="flex h-screen overflow-hidden">
<div className="flex h-screen overflow-hidden" data-testid="as-shell">
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-50 focus:bg-background focus:px-4 focus:py-2 focus:text-sm focus:font-medium focus:text-foreground focus:ring-2 focus:ring-ring focus:outline-none"
Expand Down
Loading
Loading