mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
331 lines
13 KiB
TypeScript
331 lines
13 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
test.describe("Kanban Board", () => {
|
|
// Helper to set up a mock project in localStorage
|
|
async function setupMockProject(page: ReturnType<typeof test.step>) {
|
|
await page.addInitScript(() => {
|
|
const mockProject = {
|
|
id: "test-project-1",
|
|
name: "Test Project",
|
|
path: "/mock/test-project",
|
|
lastOpened: new Date().toISOString(),
|
|
};
|
|
localStorage.setItem("automaker-storage", JSON.stringify({
|
|
state: {
|
|
projects: [mockProject],
|
|
currentProject: mockProject,
|
|
currentView: "board",
|
|
sidebarOpen: true,
|
|
theme: "dark",
|
|
},
|
|
version: 0,
|
|
}));
|
|
});
|
|
}
|
|
|
|
test("renders Kanban columns when project is open", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Should show the board view
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Check all columns are visible
|
|
await expect(page.getByTestId("kanban-column-backlog")).toBeVisible();
|
|
await expect(page.getByTestId("kanban-column-planned")).toBeVisible();
|
|
await expect(page.getByTestId("kanban-column-in_progress")).toBeVisible();
|
|
await expect(page.getByTestId("kanban-column-review")).toBeVisible();
|
|
await expect(page.getByTestId("kanban-column-verified")).toBeVisible();
|
|
await expect(page.getByTestId("kanban-column-failed")).toBeVisible();
|
|
});
|
|
|
|
test("shows Add Feature button", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
await expect(page.getByTestId("add-feature-button")).toBeVisible();
|
|
});
|
|
|
|
test("opens add feature dialog", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Click add feature button
|
|
await page.getByTestId("add-feature-button").click();
|
|
|
|
// Dialog should appear
|
|
await expect(page.getByTestId("add-feature-dialog")).toBeVisible();
|
|
await expect(page.getByTestId("feature-category-input")).toBeVisible();
|
|
await expect(page.getByTestId("feature-description-input")).toBeVisible();
|
|
});
|
|
|
|
test("can add a new feature", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Click add feature button
|
|
await page.getByTestId("add-feature-button").click();
|
|
|
|
// Fill in feature details
|
|
await page.getByTestId("feature-category-input").fill("Test Category");
|
|
await page.getByTestId("feature-description-input").fill("Test Feature Description");
|
|
await page.getByTestId("feature-step-0-input").fill("Step 1: First step");
|
|
|
|
// Submit the form
|
|
await page.getByTestId("confirm-add-feature").click();
|
|
|
|
// Dialog should close
|
|
await expect(page.getByTestId("add-feature-dialog")).not.toBeVisible();
|
|
});
|
|
|
|
test("refresh button is visible", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
await expect(page.getByTestId("refresh-board")).toBeVisible();
|
|
});
|
|
|
|
test("loads cards from feature_list.json and displays them in correct columns", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for loading to complete (the mock IPC returns a sample feature)
|
|
// The mock returns a feature in "backlog" column (passes: false)
|
|
await expect(page.getByTestId("kanban-column-backlog")).toBeVisible();
|
|
|
|
// After loading, the backlog should show the sample feature from mock data
|
|
// Looking at the electron.ts mock, it returns one feature with "Sample Feature"
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
await expect(backlogColumn.getByText("Sample Feature")).toBeVisible();
|
|
});
|
|
|
|
test("features with passes:true appear in verified column", async ({ page }) => {
|
|
// Create a project and add a feature manually
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Add a new feature
|
|
await page.getByTestId("add-feature-button").click();
|
|
await page.getByTestId("feature-category-input").fill("Core");
|
|
await page.getByTestId("feature-description-input").fill("Verified Test Feature");
|
|
await page.getByTestId("confirm-add-feature").click();
|
|
|
|
// The new feature should appear in backlog
|
|
await expect(page.getByTestId("kanban-column-backlog").getByText("Verified Test Feature")).toBeVisible();
|
|
});
|
|
|
|
test("can edit feature card details", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load - the mock returns "Sample Feature"
|
|
await expect(page.getByTestId("kanban-column-backlog").getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Find and click the edit button on the card using specific testid pattern
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
// The edit button has testid "edit-feature-{feature.id}" where feature.id contains "feature-0-"
|
|
const editButton = backlogColumn.locator('[data-testid^="edit-feature-feature-0-"]');
|
|
await editButton.click();
|
|
|
|
// Edit dialog should appear
|
|
await expect(page.getByTestId("edit-feature-dialog")).toBeVisible();
|
|
|
|
// Edit the description
|
|
await page.getByTestId("edit-feature-description").fill("Updated Feature Description");
|
|
|
|
// Save the changes
|
|
await page.getByTestId("confirm-edit-feature").click();
|
|
|
|
// Dialog should close
|
|
await expect(page.getByTestId("edit-feature-dialog")).not.toBeVisible();
|
|
|
|
// The updated description should be visible
|
|
await expect(page.getByText("Updated Feature Description")).toBeVisible();
|
|
});
|
|
|
|
test("edit dialog shows existing feature data", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load
|
|
await expect(page.getByTestId("kanban-column-backlog").getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Click edit button using specific testid pattern
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
const editButton = backlogColumn.locator('[data-testid^="edit-feature-feature-0-"]');
|
|
await editButton.click();
|
|
|
|
// Check that the dialog pre-populates with existing data
|
|
await expect(page.getByTestId("edit-feature-description")).toHaveValue("Sample Feature");
|
|
await expect(page.getByTestId("edit-feature-category")).toHaveValue("Core");
|
|
});
|
|
|
|
test("can drag card from Backlog to In Progress column", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load in Backlog
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
const inProgressColumn = page.getByTestId("kanban-column-in_progress");
|
|
|
|
await expect(backlogColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Find the drag handle specifically
|
|
const dragHandle = backlogColumn.locator('[data-testid^="drag-handle-feature-0-"]');
|
|
await expect(dragHandle).toBeVisible();
|
|
|
|
// Get drag handle and target positions
|
|
const handleBox = await dragHandle.boundingBox();
|
|
const targetBox = await inProgressColumn.boundingBox();
|
|
if (!handleBox || !targetBox) throw new Error("Could not find elements");
|
|
|
|
// Use mouse events - start from center of drag handle
|
|
const startX = handleBox.x + handleBox.width / 2;
|
|
const startY = handleBox.y + handleBox.height / 2;
|
|
const endX = targetBox.x + targetBox.width / 2;
|
|
const endY = targetBox.y + 100;
|
|
|
|
await page.mouse.move(startX, startY);
|
|
await page.mouse.down();
|
|
|
|
// Move in steps to trigger dnd-kit activation (needs >8px movement)
|
|
await page.mouse.move(endX, endY, { steps: 20 });
|
|
await page.mouse.up();
|
|
|
|
// Verify card moved to In Progress column
|
|
await expect(inProgressColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Verify card is no longer in Backlog
|
|
await expect(backlogColumn.getByText("Sample Feature")).not.toBeVisible();
|
|
});
|
|
|
|
test("drag and drop updates feature status and triggers file save", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load in Backlog
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
const plannedColumn = page.getByTestId("kanban-column-planned");
|
|
|
|
await expect(backlogColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Find the drag handle specifically
|
|
const dragHandle = backlogColumn.locator('[data-testid^="drag-handle-feature-0-"]');
|
|
await expect(dragHandle).toBeVisible();
|
|
|
|
// Get drag handle and target positions (Planned is adjacent to Backlog)
|
|
const handleBox = await dragHandle.boundingBox();
|
|
const targetBox = await plannedColumn.boundingBox();
|
|
if (!handleBox || !targetBox) throw new Error("Could not find elements");
|
|
|
|
// Use mouse events - start from center of drag handle
|
|
const startX = handleBox.x + handleBox.width / 2;
|
|
const startY = handleBox.y + handleBox.height / 2;
|
|
const endX = targetBox.x + targetBox.width / 2;
|
|
const endY = targetBox.y + 100;
|
|
|
|
await page.mouse.move(startX, startY);
|
|
await page.mouse.down();
|
|
|
|
// Move in steps to trigger dnd-kit activation (needs >8px movement)
|
|
await page.mouse.move(endX, endY, { steps: 20 });
|
|
await page.mouse.up();
|
|
|
|
// Verify card moved to Planned column
|
|
await expect(plannedColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Verify card is no longer in Backlog
|
|
await expect(backlogColumn.getByText("Sample Feature")).not.toBeVisible();
|
|
|
|
// The feature moving to Planned means the feature_list.json would be updated
|
|
// with the new status. Since status changed from backlog, passes would remain false
|
|
// This confirms the state update and file save workflow works.
|
|
const plannedCard = plannedColumn.locator('[data-testid^="kanban-card-feature-0-"]');
|
|
await expect(plannedCard).toBeVisible();
|
|
});
|
|
|
|
test("displays delete button (trash icon) on feature card", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load in Backlog
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
await expect(backlogColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Find the delete button on the card
|
|
const deleteButton = backlogColumn.locator('[data-testid^="delete-feature-feature-0-"]');
|
|
await expect(deleteButton).toBeVisible();
|
|
});
|
|
|
|
test("can delete a feature from kanban board", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Wait for features to load in Backlog
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
await expect(backlogColumn.getByText("Sample Feature")).toBeVisible();
|
|
|
|
// Find and click the delete button
|
|
const deleteButton = backlogColumn.locator('[data-testid^="delete-feature-feature-0-"]');
|
|
await deleteButton.click();
|
|
|
|
// Verify the feature is removed from the board
|
|
await expect(backlogColumn.getByText("Sample Feature")).not.toBeVisible();
|
|
});
|
|
|
|
test("deleting feature removes it from all columns", async ({ page }) => {
|
|
await setupMockProject(page);
|
|
await page.goto("/");
|
|
|
|
// Wait for board to load
|
|
await expect(page.getByTestId("board-view")).toBeVisible();
|
|
|
|
// Add a new feature first
|
|
await page.getByTestId("add-feature-button").click();
|
|
await page.getByTestId("feature-category-input").fill("Test Category");
|
|
await page.getByTestId("feature-description-input").fill("Feature to Delete");
|
|
await page.getByTestId("confirm-add-feature").click();
|
|
|
|
// Wait for the new feature to appear in backlog
|
|
const backlogColumn = page.getByTestId("kanban-column-backlog");
|
|
await expect(backlogColumn.getByText("Feature to Delete")).toBeVisible();
|
|
|
|
// Find and click the delete button for the newly added feature
|
|
const deleteButton = backlogColumn.locator('[data-testid^="delete-feature-feature-"]').last();
|
|
await deleteButton.click();
|
|
|
|
// Verify the feature is removed
|
|
await expect(backlogColumn.getByText("Feature to Delete")).not.toBeVisible();
|
|
|
|
// Also verify it's not anywhere else on the board
|
|
await expect(page.getByText("Feature to Delete")).not.toBeVisible();
|
|
});
|
|
});
|