import { test, expect } from '@playwright/test'; import { waitForAppReady, setupConsoleCollector, resetMockState } from './helpers.js'; test.describe('Workspace templates', () => { let consoleCollector; test.beforeEach(async ({ page }) => { consoleCollector = setupConsoleCollector(page); await resetMockState(page); await page.goto('/'); await waitForAppReady(page); }); test.afterEach(async () => { consoleCollector.assertNoErrors(); }); async function openCreateModal(page) { await page.locator('button[title="New Deal"]').click(); const modal = page.locator('[data-workspace-create-modal]'); await expect(modal).toBeVisible(); return modal; } test('creation modal validates names, shows template tools, and persists the selected snapshot', async ({ page }) => { const modal = await openCreateModal(page); const templateSelect = modal.locator('[data-workspace-template]'); await expect(templateSelect).toHaveValue('default'); await expect(templateSelect).toHaveCSS('appearance', 'none'); await expect(modal.locator('[data-workspace-template-tools]')).toContainText('Notes'); await expect(modal.locator('[data-workspace-template-tools]')).toContainText('Browser'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(modal.locator('[data-workspace-create-error]')).toContainText('Name is required'); await modal.locator('[data-workspace-name]').fill('bad/name'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(modal.locator('[data-workspace-create-error]')).toContainText('Could not create the Deal. Please try again.'); await modal.locator('[data-workspace-name]').fill('ProjectPlan'); await modal.locator('[data-workspace-template]').selectOption('project'); await expect(modal.locator('[data-workspace-template-description]')).toContainText('Project planning'); await expect(modal.locator('[data-workspace-template-tools]')).toContainText('Todos'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(page.locator('.wt-label').filter({ hasText: 'ProjectPlan' })).toBeVisible(); await expect.poll(async () => page.evaluate(async () => { const result = await window.go.api.App.GetWorkspaceMetadata('ProjectPlan'); const metadata = Array.isArray(result) ? result[0] : result; return { templateId: metadata.createdFromTemplate?.templateId, tools: metadata.workspaceTools, }; })).toEqual({ templateId: 'project', tools: ['verstak.notes', 'verstak.files', 'verstak.todo', 'verstak.journal', 'verstak.activity', 'verstak.browser-inbox'], }); await expect(page.getByRole('tab', { name: 'Todos' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Journal' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Secrets' })).toHaveCount(0); }); test('Minimal keeps global tools available while limiting workspace tabs', async ({ page }) => { const modal = await openCreateModal(page); await modal.locator('[data-workspace-name]').fill('MinimalSpace'); await modal.locator('[data-workspace-template]').selectOption('minimal'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(page.getByRole('tab', { name: 'Overview' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Notes' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Files' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Todos' })).toHaveCount(0); await expect(page.getByRole('tab', { name: 'Journal' })).toHaveCount(0); await expect(page.getByRole('tab', { name: 'Secrets' })).toHaveCount(0); await expect(page.locator('.sidebar .plugin-item').filter({ hasText: 'Todos' })).toBeVisible(); await expect(page.locator('.sidebar .plugin-item').filter({ hasText: 'Browser' })).toBeVisible(); }); test('template explains an unavailable plugin and warns after incomplete creation', async ({ page }) => { await page.evaluate(() => window.__wailsMock.setPluginStatus('verstak.todo', 'disabled', false)); const modal = await openCreateModal(page); await modal.locator('[data-workspace-template]').selectOption('project'); const todo = modal.locator('[data-workspace-template-tool="verstak.todo"]'); await expect(todo).toContainText('Todos'); await expect(todo).toContainText('Plugin is disabled'); await expect(todo).toHaveAttribute('data-template-tool-status', 'unavailable'); await modal.locator('[data-workspace-name]').fill('ProjectWithWarning'); await modal.getByRole('button', { name: 'Create Deal' }).click(); const warning = page.locator('[data-workspace-template-warning]'); await expect(warning).toContainText('ProjectWithWarning'); await expect(warning).toContainText('Todos'); await expect(warning).toContainText('Plugin is disabled'); }); test('Admin shows Secrets when available and missing workspace plugins degrade without breaking tabs', async ({ page }) => { let modal = await openCreateModal(page); await modal.locator('[data-workspace-name]').fill('AdminSpace'); await modal.locator('[data-workspace-template]').selectOption('admin'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(page.getByRole('tab', { name: 'Secrets' })).toBeVisible(); await page.evaluate(() => window.__wailsMock.setPluginStatus('verstak.todo', 'disabled', false)); modal = await openCreateModal(page); await modal.locator('[data-workspace-name]').fill('ProjectWithoutTodo'); await modal.locator('[data-workspace-template]').selectOption('project'); await modal.getByRole('button', { name: 'Create Deal' }).click(); await expect(page.getByRole('tab', { name: 'Notes' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Files' })).toBeVisible(); await expect(page.getByRole('tab', { name: 'Todos' })).toHaveCount(0); await page.locator('.wt-label').filter({ hasText: 'AdminSpace' }).click(); await expect(page.getByRole('tab', { name: 'Secrets' })).toBeVisible(); }); });