* feat: chroots * wip * Update workspace templates and Playwright tests * Fix thinking panel close button not working during active thinking The auto-show useEffect was including showThinkingPanel in its dependency array, causing the panel to immediately reopen when closed since the state change would trigger the effect while hasActiveThinking was still true. Changed to use a ref to track previous state and only auto-show on transition from inactive to active thinking. * wip * wip * wip * Cleanup web search tool and remove hardcoded OAuth credentials * Ralph iteration 1: work in progress * Ralph iteration 2: work in progress * Ralph iteration 3: work in progress * Ralph iteration 4: work in progress * Ralph iteration 5: work in progress * Ralph iteration 6: work in progress * Ralph iteration 1: work in progress * Ralph iteration 2: work in progress * Ralph iteration 3: work in progress * Ralph iteration 4: work in progress * Ralph iteration 5: work in progress * Ralph iteration 6: work in progress * Ralph iteration 7: work in progress * Ralph iteration 1: work in progress * Ralph iteration 2: work in progress * improve readme * fix: remove unused file * feat: hero screenshot * Update README with cleaner vision and hero screenshot Simplified the vision section with "what if" framing, removed architecture diagram, added hero screenshot showing mission view.
92 lines
3.3 KiB
TypeScript
92 lines
3.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Workspaces Page', () => {
|
|
test('should load workspaces page', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Check for page title
|
|
await expect(page.getByRole('heading', { name: 'Workspaces' })).toBeVisible();
|
|
|
|
// Check for "New Workspace" button
|
|
await expect(page.getByRole('button', { name: /New Workspace/i })).toBeVisible();
|
|
});
|
|
|
|
test('should show empty state or workspace cards', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Wait for loading
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Either shows empty state or workspace cards
|
|
const emptyState = await page.getByText(/No workspaces yet/i).isVisible().catch(() => false);
|
|
const hasCards = await page.locator('[class*="rounded-xl"]').count() > 0;
|
|
|
|
expect(emptyState || hasCards).toBeTruthy();
|
|
});
|
|
|
|
test('should open new workspace dialog', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Click "New Workspace" button
|
|
await page.getByRole('button', { name: /New Workspace/i }).click();
|
|
|
|
// Check dialog appears
|
|
await expect(page.getByRole('heading', { name: 'New Workspace' })).toBeVisible();
|
|
|
|
// Check for name input
|
|
await expect(page.getByPlaceholder(/workspace|name/i)).toBeVisible();
|
|
|
|
// Check for template and type selectors
|
|
await expect(page.getByText('Template').locator('..').locator('select')).toBeVisible();
|
|
await expect(page.getByText('Type').locator('..').locator('select')).toBeVisible();
|
|
});
|
|
|
|
test('should validate workspace creation form', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Open new workspace dialog
|
|
await page.getByRole('button', { name: /New Workspace/i }).click();
|
|
|
|
// Try to create without name
|
|
const createButton = page.getByRole('button', { name: /Create/i });
|
|
await expect(createButton).toBeDisabled();
|
|
|
|
// Fill in name
|
|
await page.getByPlaceholder(/workspace|name/i).fill('test-workspace');
|
|
|
|
// Now button should be enabled
|
|
await expect(createButton).toBeEnabled();
|
|
});
|
|
|
|
test('should show workspace type options', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Open new workspace dialog
|
|
await page.getByRole('button', { name: /New Workspace/i }).click();
|
|
|
|
// Check type selector has options
|
|
const select = page.getByText('Type').locator('..').locator('select');
|
|
await expect(select).toBeVisible();
|
|
|
|
// Should have Host and Chroot options
|
|
const options = await select.locator('option').allTextContents();
|
|
expect(options.some(opt => opt.toLowerCase().includes('host'))).toBeTruthy();
|
|
expect(options.some(opt => opt.toLowerCase().includes('isolated'))).toBeTruthy();
|
|
});
|
|
|
|
test('should show template selector options', async ({ page }) => {
|
|
await page.goto('/workspaces');
|
|
|
|
// Open new workspace dialog
|
|
await page.getByRole('button', { name: /New Workspace/i }).click();
|
|
|
|
const templateSelect = page.getByText('Template').locator('..').locator('select');
|
|
await expect(templateSelect).toBeVisible();
|
|
|
|
const options = await templateSelect.locator('option').allTextContents();
|
|
expect(
|
|
options.some(opt => opt.toLowerCase().includes('none') || opt.toLowerCase().includes('no template'))
|
|
).toBeTruthy();
|
|
});
|
|
});
|