Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ dist-ssr
*.njsproj
*.sln
*.sw?
coverage

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

# Dolt database files (added by bd init)
.dolt/
*.db
114 changes: 114 additions & 0 deletions e2e/tiptap-editor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { test, expect } from '@playwright/test';

/**
* E2E tests for the TipTap Template Editor.
*
* These tests verify keyboard navigation and toolbar interactions
* when the rich editor feature is enabled.
*/
test.describe('TipTap Template Editor', () => {
test.beforeEach(async ({ page }) => {
// Set localStorage to enable rich editor before navigating
await page.addInitScript(() => {
localStorage.setItem('hasVisited', 'true');
localStorage.setItem('useRichEditor', 'true');
});

await page.goto('/');
await expect(page.locator('.app-spinner-container')).toBeHidden({ timeout: 30000 });
});

test('should show Beta tag when rich editor is enabled', async ({ page }) => {
// The Beta tag should be visible in the Template panel header
const betaTag = page.locator('.ant-tag').filter({ hasText: 'Beta' });
await expect(betaTag).toBeVisible();
});

test('should display rich editor toolbar', async ({ page }) => {
// Look for the TipTap editor toolbar
const toolbar = page.locator('.ap-template-editor [role="toolbar"]');
await expect(toolbar).toBeVisible({ timeout: 5000 });
});

test('should toggle between rich and markdown view with Ctrl+M', async ({ page }) => {
// Wait for the TipTap editor to be visible
const tiptapEditor = page.locator('.ap-template-editor');
await expect(tiptapEditor).toBeVisible({ timeout: 5000 });

// Rich editor content should be visible initially
const richContent = page.locator('.ap-template-editor__content');
await expect(richContent).toBeVisible();

// Press Ctrl+M to toggle to markdown view
await page.keyboard.press('Control+m');

// After toggle, the Monaco editor should be visible (markdown mode)
// Wait a moment for the view to switch
await page.waitForTimeout(500);

// Press Ctrl+M again to toggle back
await page.keyboard.press('Control+m');

// Rich editor content should be visible again
await expect(richContent).toBeVisible({ timeout: 2000 });
});

test('toolbar Insert dropdown should open dialog', async ({ page }) => {
// Wait for toolbar to be visible
const toolbar = page.locator('.ap-template-editor [role="toolbar"]');
await expect(toolbar).toBeVisible({ timeout: 5000 });

// Click the Insert dropdown trigger (look for Insert or Variables button)
const insertButton = toolbar.locator('button').filter({ hasText: /insert|variable/i }).first();

// If the button exists, click it to open the dropdown
if (await insertButton.isVisible()) {
await insertButton.click();

// Look for dropdown menu items
const menuItem = page.locator('[role="menuitem"]').first();
if (await menuItem.isVisible({ timeout: 2000 })) {
await menuItem.click();

// A dialog should open for inserting the template element
const dialog = page.locator('.ap-insert-dialog, [role="dialog"]');
await expect(dialog).toBeVisible({ timeout: 2000 });
}
}
});

test('should hide standard toolbar when rich editor is enabled', async ({ page }) => {
// The TemplateMarkdownToolbar should NOT be visible when rich editor is enabled
// Look for the toolbar that appears above the Monaco editor normally
const standardToolbar = page.locator('.template-markdown-toolbar');

// It should either not exist or not be visible
const isVisible = await standardToolbar.isVisible().catch(() => false);
expect(isVisible).toBe(false);
});
});

test.describe('TipTap Editor Disabled', () => {
test.beforeEach(async ({ page }) => {
// Ensure rich editor is disabled
await page.addInitScript(() => {
localStorage.setItem('hasVisited', 'true');
localStorage.setItem('useRichEditor', 'false');
});

await page.goto('/');
await expect(page.locator('.app-spinner-container')).toBeHidden({ timeout: 30000 });
});

test('should NOT show Beta tag when rich editor is disabled', async ({ page }) => {
// The Beta tag should not be visible
const betaTag = page.locator('.ant-tag').filter({ hasText: 'Beta' });
await expect(betaTag).not.toBeVisible();
});

test('should show standard Monaco editor when rich editor is disabled', async ({ page }) => {
// Look for the Monaco editor container
const monacoEditor = page.locator('.monaco-editor');
await expect(monacoEditor.first()).toBeVisible({ timeout: 5000 });
});
});
Loading