mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 14:22:02 +00:00
399 lines
16 KiB
TypeScript
399 lines
16 KiB
TypeScript
import { test, expect } from "@playwright/test";
|
|
|
|
test.describe("Interactive New Project Interview", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto("/");
|
|
});
|
|
|
|
test("Step 1: Click 'New Project' -> 'Interactive Mode' navigates to interview view", async ({ page }) => {
|
|
// Click the Create Project dropdown button
|
|
await page.getByTestId("create-new-project").click();
|
|
|
|
// Wait for dropdown to appear and click Interactive Mode option
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Verify the header shows "New Project Interview"
|
|
await expect(page.getByText("New Project Interview")).toBeVisible();
|
|
});
|
|
|
|
test("Step 2: Chat interface appears asking 'What do you want to build?'", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Verify the first question is displayed
|
|
await expect(page.getByTestId("interview-messages")).toBeVisible();
|
|
await expect(page.getByText("What do you want to build?")).toBeVisible();
|
|
|
|
// Verify input field is available
|
|
await expect(page.getByTestId("interview-input")).toBeVisible();
|
|
await expect(page.getByTestId("interview-send")).toBeVisible();
|
|
});
|
|
|
|
test("Step 3: User can reply 'A todo app'", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Type the answer in the input field
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
|
|
// Click send button
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Verify user message appears in the chat
|
|
await expect(page.getByTestId("interview-messages").getByText("A todo app")).toBeVisible();
|
|
});
|
|
|
|
test("Step 4: Agent asks clarifying questions (tech stack)", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Wait for interview view
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Answer first question
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for the next question to appear (tech stack question)
|
|
await expect(page.getByText("What tech stack would you like to use?")).toBeVisible({ timeout: 5000 });
|
|
|
|
// Verify progress text shows question 2 of 4
|
|
await expect(page.getByText("Question 2 of 4")).toBeVisible();
|
|
});
|
|
|
|
test("Step 5: Agent generates draft app_spec.txt based on conversation", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Wait for interview view
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Answer first question - project description
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for tech stack question
|
|
await expect(page.getByText("What tech stack would you like to use?")).toBeVisible({ timeout: 5000 });
|
|
|
|
// Answer tech stack question
|
|
await page.getByTestId("interview-input").fill("React, Next.js, TypeScript");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for features question
|
|
await expect(page.getByText("What are the core features you want to include?")).toBeVisible({ timeout: 5000 });
|
|
|
|
// Answer features question
|
|
await page.getByTestId("interview-input").fill("Add tasks, Mark complete, Delete tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for additional requirements question
|
|
await expect(page.getByText("Any additional requirements or preferences?")).toBeVisible({ timeout: 5000 });
|
|
|
|
// Answer additional requirements
|
|
await page.getByTestId("interview-input").fill("Dark mode support");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for spec generation to complete
|
|
await expect(page.getByTestId("project-setup-form")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Verify spec preview is visible with generated content
|
|
await expect(page.getByTestId("spec-preview")).toBeVisible();
|
|
|
|
// Verify the generated spec contains the project description
|
|
const specPreview = page.getByTestId("spec-preview");
|
|
await expect(specPreview).toContainText("A todo app");
|
|
|
|
// Verify it contains tech stack information
|
|
await expect(specPreview).toContainText("React");
|
|
|
|
// Verify it contains features
|
|
await expect(specPreview).toContainText("Add tasks");
|
|
});
|
|
|
|
test("Interview shows progress indicator with correct number of steps", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Verify progress text shows question 1 of 4
|
|
await expect(page.getByText("Question 1 of 4")).toBeVisible();
|
|
});
|
|
|
|
test("Send button is disabled when input is empty", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify send button is disabled when input is empty
|
|
await expect(page.getByTestId("interview-send")).toBeDisabled();
|
|
|
|
// Type something
|
|
await page.getByTestId("interview-input").fill("Test");
|
|
|
|
// Now button should be enabled
|
|
await expect(page.getByTestId("interview-send")).toBeEnabled();
|
|
|
|
// Clear input
|
|
await page.getByTestId("interview-input").fill("");
|
|
|
|
// Button should be disabled again
|
|
await expect(page.getByTestId("interview-send")).toBeDisabled();
|
|
});
|
|
|
|
test("Can submit answer by pressing Enter", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Type answer and press Enter
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
await page.getByTestId("interview-input").press("Enter");
|
|
|
|
// Verify user message appears
|
|
await expect(page.getByTestId("interview-messages").getByText("A todo app")).toBeVisible();
|
|
});
|
|
|
|
test("Back button returns to welcome view", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// Click back button
|
|
await page.getByTestId("interview-back-button").click();
|
|
|
|
// Verify we're back on welcome view
|
|
await expect(page.getByTestId("welcome-view")).toBeVisible();
|
|
});
|
|
|
|
test("Project setup form appears after completing interview", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Complete all questions
|
|
await page.getByTestId("interview-input").fill("A simple todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What tech stack would you like to use?")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("React");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What are the core features")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Add, edit, delete tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("Any additional requirements")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("None");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for project setup form
|
|
await expect(page.getByTestId("project-setup-form")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Verify form has name input
|
|
await expect(page.getByTestId("interview-project-name-input")).toBeVisible();
|
|
|
|
// Verify form has path input
|
|
await expect(page.getByTestId("interview-project-path-input")).toBeVisible();
|
|
|
|
// Verify browse directory button
|
|
await expect(page.getByTestId("interview-browse-directory")).toBeVisible();
|
|
|
|
// Verify create project button
|
|
await expect(page.getByTestId("interview-create-project")).toBeVisible();
|
|
});
|
|
|
|
test("Create project button is disabled without name and path", async ({ page }) => {
|
|
// Navigate to interview view and complete interview
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Complete all questions quickly
|
|
await page.getByTestId("interview-input").fill("A simple todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What tech stack")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("React");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("core features")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("additional requirements")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("None");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for project setup form
|
|
await expect(page.getByTestId("project-setup-form")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Create button should be disabled without name and path
|
|
await expect(page.getByTestId("interview-create-project")).toBeDisabled();
|
|
|
|
// Enter project name
|
|
await page.getByTestId("interview-project-name-input").fill("my-todo-app");
|
|
|
|
// Still disabled (no path)
|
|
await expect(page.getByTestId("interview-create-project")).toBeDisabled();
|
|
|
|
// Enter path
|
|
await page.getByTestId("interview-project-path-input").fill("/Users/test/projects");
|
|
|
|
// Now should be enabled
|
|
await expect(page.getByTestId("interview-create-project")).toBeEnabled();
|
|
});
|
|
|
|
test("Creates project and navigates to board view after interview", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Complete all questions
|
|
await page.getByTestId("interview-input").fill("A simple todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What tech stack")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("React");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("core features")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("additional requirements")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("None");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for project setup form
|
|
await expect(page.getByTestId("project-setup-form")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Fill in project details
|
|
await page.getByTestId("interview-project-name-input").fill("interview-test-project");
|
|
await page.getByTestId("interview-project-path-input").fill("/Users/test/projects");
|
|
|
|
// Click create
|
|
await page.getByTestId("interview-create-project").click();
|
|
|
|
// Should navigate to board view
|
|
await expect(page.getByTestId("board-view")).toBeVisible({ timeout: 5000 });
|
|
|
|
// Project name should be visible
|
|
await expect(page.getByTestId("board-view").getByText("interview-test-project")).toBeVisible();
|
|
});
|
|
|
|
test("Interview messages have timestamps", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Verify interview view is displayed
|
|
await expect(page.getByTestId("interview-view")).toBeVisible();
|
|
|
|
// The welcome message should have a timestamp displayed
|
|
// Timestamps are in format like "10:30:45 AM" or similar
|
|
const messagesArea = page.getByTestId("interview-messages");
|
|
await expect(messagesArea).toBeVisible();
|
|
|
|
// The welcome message should contain the first question
|
|
await expect(messagesArea.getByText("What do you want to build?")).toBeVisible();
|
|
|
|
// The message area should contain timestamp text (time format like "10:30:45 AM")
|
|
// We verify by checking that the welcome message exists and has content
|
|
await expect(messagesArea.locator("p.text-sm").first()).toBeVisible();
|
|
});
|
|
|
|
test("Input field is hidden after interview completes", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Complete all questions
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What tech stack")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("React");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("core features")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("additional requirements")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("None");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for project setup form (interview complete)
|
|
await expect(page.getByTestId("project-setup-form")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Input field should no longer be visible
|
|
await expect(page.getByTestId("interview-input")).not.toBeVisible();
|
|
});
|
|
|
|
test("Generated spec contains proper XML structure", async ({ page }) => {
|
|
// Navigate to interview view
|
|
await page.getByTestId("create-new-project").click();
|
|
await page.getByTestId("interactive-mode-option").click();
|
|
|
|
// Complete all questions
|
|
await page.getByTestId("interview-input").fill("A todo app");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("What tech stack")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("React, TypeScript");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("core features")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Add tasks, Delete tasks");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
await expect(page.getByText("additional requirements")).toBeVisible({ timeout: 5000 });
|
|
await page.getByTestId("interview-input").fill("Mobile responsive");
|
|
await page.getByTestId("interview-send").click();
|
|
|
|
// Wait for spec preview
|
|
await expect(page.getByTestId("spec-preview")).toBeVisible({ timeout: 10000 });
|
|
|
|
// Verify XML structure elements
|
|
const specPreview = page.getByTestId("spec-preview");
|
|
await expect(specPreview).toContainText("<project_specification>");
|
|
await expect(specPreview).toContainText("<overview>");
|
|
await expect(specPreview).toContainText("<technology_stack>");
|
|
await expect(specPreview).toContainText("<core_capabilities>");
|
|
await expect(specPreview).toContainText("<development_guidelines>");
|
|
});
|
|
|
|
test("Quick Setup option still works from dropdown", async ({ page }) => {
|
|
// Click the Create Project dropdown button
|
|
await page.getByTestId("create-new-project").click();
|
|
|
|
// Click Quick Setup option
|
|
await page.getByTestId("quick-setup-option").click();
|
|
|
|
// Verify dialog appears (not interview view)
|
|
await expect(page.getByTestId("new-project-dialog")).toBeVisible();
|
|
await expect(page.getByText("Create New Project")).toBeVisible();
|
|
});
|
|
});
|