mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-19 10:43:08 +00:00
Make memory and context views mobile-friendly (#813)
* Changes from fix/memory-and-context-mobile-friendly * fix: Improve file extension detection and add path traversal protection * refactor: Extract file extension utilities and add path traversal guards Code review improvements: - Extract isMarkdownFilename and isImageFilename to shared image-utils.ts - Remove duplicated code from context-view.tsx and memory-view.tsx - Add path traversal guard for context fixture utilities (matching memory) - Add 7 new tests for context fixture path traversal protection - Total 61 tests pass Addresses code review feedback from PR #813 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: Add e2e tests for profiles crud and board background persistence * Update apps/ui/playwright.config.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: Add robust test navigation handling and file filtering * fix: Format NODE_OPTIONS configuration on single line * test: Update profiles and board background persistence tests * test: Replace iPhone 13 Pro with Pixel 5 for mobile test consistency --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
237
apps/ui/tests/context/desktop-context-view.spec.ts
Normal file
237
apps/ui/tests/context/desktop-context-view.spec.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Desktop Context View E2E Tests
|
||||
*
|
||||
* Tests for desktop behavior in the context view:
|
||||
* - File list and editor visible side-by-side
|
||||
* - Back button is NOT visible on desktop
|
||||
* - Toolbar buttons show both icon and text
|
||||
* - Delete button is visible in toolbar (not hidden like on mobile)
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test';
|
||||
import {
|
||||
resetContextDirectory,
|
||||
setupProjectWithFixture,
|
||||
getFixturePath,
|
||||
navigateToContext,
|
||||
waitForContextFile,
|
||||
selectContextFile,
|
||||
waitForFileContentToLoad,
|
||||
clickElement,
|
||||
fillInput,
|
||||
waitForNetworkIdle,
|
||||
authenticateForTests,
|
||||
waitForElementHidden,
|
||||
} from '../utils';
|
||||
|
||||
// Use desktop viewport for desktop tests
|
||||
test.use({ viewport: { width: 1280, height: 720 } });
|
||||
|
||||
test.describe('Desktop Context View', () => {
|
||||
test.beforeEach(async () => {
|
||||
resetContextDirectory();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
resetContextDirectory();
|
||||
});
|
||||
|
||||
test('should show file list and editor side-by-side on desktop', async ({ page }) => {
|
||||
const fileName = 'desktop-test.md';
|
||||
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// Create a test file
|
||||
await clickElement(page, 'create-markdown-button');
|
||||
await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
|
||||
|
||||
await fillInput(page, 'new-markdown-name', fileName);
|
||||
await fillInput(
|
||||
page,
|
||||
'new-markdown-content',
|
||||
'# Desktop Test\n\nThis tests desktop view behavior'
|
||||
);
|
||||
|
||||
await clickElement(page, 'confirm-create-markdown');
|
||||
|
||||
await waitForElementHidden(page, 'create-markdown-dialog', { timeout: 5000 });
|
||||
|
||||
await waitForNetworkIdle(page);
|
||||
await waitForContextFile(page, fileName);
|
||||
|
||||
// Select the file
|
||||
await selectContextFile(page, fileName);
|
||||
await waitForFileContentToLoad(page);
|
||||
|
||||
// On desktop, file list should be visible after selection
|
||||
const fileList = page.locator('[data-testid="context-file-list"]');
|
||||
await expect(fileList).toBeVisible();
|
||||
|
||||
// Editor panel should also be visible
|
||||
const editor = page.locator('[data-testid="context-editor"], [data-testid="markdown-preview"]');
|
||||
await expect(editor).toBeVisible();
|
||||
});
|
||||
|
||||
test('should NOT show back button in editor toolbar on desktop', async ({ page }) => {
|
||||
const fileName = 'no-back-button-test.md';
|
||||
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// Create a test file
|
||||
await clickElement(page, 'create-markdown-button');
|
||||
await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
|
||||
|
||||
await fillInput(page, 'new-markdown-name', fileName);
|
||||
await fillInput(page, 'new-markdown-content', '# No Back Button Test');
|
||||
|
||||
await clickElement(page, 'confirm-create-markdown');
|
||||
|
||||
await waitForElementHidden(page, 'create-markdown-dialog', { timeout: 5000 });
|
||||
|
||||
await waitForNetworkIdle(page);
|
||||
await waitForContextFile(page, fileName);
|
||||
|
||||
// Select the file
|
||||
await selectContextFile(page, fileName);
|
||||
await waitForFileContentToLoad(page);
|
||||
|
||||
// Back button should NOT be visible on desktop
|
||||
const backButton = page.locator('button[aria-label="Back"]');
|
||||
await expect(backButton).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('should show buttons with text labels on desktop', async ({ page }) => {
|
||||
const fileName = 'text-labels-test.md';
|
||||
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// Create a test file
|
||||
await clickElement(page, 'create-markdown-button');
|
||||
await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
|
||||
|
||||
await fillInput(page, 'new-markdown-name', fileName);
|
||||
await fillInput(
|
||||
page,
|
||||
'new-markdown-content',
|
||||
'# Text Labels Test\n\nTesting button text labels on desktop'
|
||||
);
|
||||
|
||||
await clickElement(page, 'confirm-create-markdown');
|
||||
|
||||
await waitForElementHidden(page, 'create-markdown-dialog', { timeout: 5000 });
|
||||
|
||||
await waitForNetworkIdle(page);
|
||||
await waitForContextFile(page, fileName);
|
||||
|
||||
// Select the file
|
||||
await selectContextFile(page, fileName);
|
||||
await waitForFileContentToLoad(page);
|
||||
|
||||
// Get the toggle preview mode button
|
||||
const toggleButton = page.locator('[data-testid="toggle-preview-mode"]');
|
||||
await expect(toggleButton).toBeVisible();
|
||||
|
||||
// Button should have text label on desktop
|
||||
const buttonText = await toggleButton.textContent();
|
||||
// On desktop, button should have visible text (Edit or Preview)
|
||||
expect(buttonText?.trim()).not.toBe('');
|
||||
expect(buttonText?.toLowerCase()).toMatch(/(edit|preview)/);
|
||||
});
|
||||
|
||||
test('should show delete button in toolbar on desktop', async ({ page }) => {
|
||||
const fileName = 'delete-button-desktop-test.md';
|
||||
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// Create a test file
|
||||
await clickElement(page, 'create-markdown-button');
|
||||
await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
|
||||
|
||||
await fillInput(page, 'new-markdown-name', fileName);
|
||||
await fillInput(page, 'new-markdown-content', '# Delete Button Desktop Test');
|
||||
|
||||
await clickElement(page, 'confirm-create-markdown');
|
||||
|
||||
await waitForElementHidden(page, 'create-markdown-dialog', { timeout: 5000 });
|
||||
|
||||
await waitForNetworkIdle(page);
|
||||
await waitForContextFile(page, fileName);
|
||||
|
||||
// Select the file
|
||||
await selectContextFile(page, fileName);
|
||||
await waitForFileContentToLoad(page);
|
||||
|
||||
// Delete button in toolbar should be visible on desktop
|
||||
const deleteButton = page.locator('[data-testid="delete-context-file"]');
|
||||
await expect(deleteButton).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show file list at fixed width on desktop when file is selected', async ({
|
||||
page,
|
||||
}) => {
|
||||
const fileName = 'fixed-width-test.md';
|
||||
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// Create a test file
|
||||
await clickElement(page, 'create-markdown-button');
|
||||
await page.waitForSelector('[data-testid="create-markdown-dialog"]', { timeout: 5000 });
|
||||
|
||||
await fillInput(page, 'new-markdown-name', fileName);
|
||||
await fillInput(page, 'new-markdown-content', '# Fixed Width Test');
|
||||
|
||||
await clickElement(page, 'confirm-create-markdown');
|
||||
|
||||
await waitForElementHidden(page, 'create-markdown-dialog', { timeout: 5000 });
|
||||
|
||||
await waitForNetworkIdle(page);
|
||||
await waitForContextFile(page, fileName);
|
||||
|
||||
// Select the file
|
||||
await selectContextFile(page, fileName);
|
||||
await waitForFileContentToLoad(page);
|
||||
|
||||
// File list should be visible
|
||||
const fileList = page.locator('[data-testid="context-file-list"]');
|
||||
await expect(fileList).toBeVisible();
|
||||
|
||||
// On desktop with file selected, the file list should be at fixed width (w-64 = 256px)
|
||||
const fileListBox = await fileList.boundingBox();
|
||||
expect(fileListBox).not.toBeNull();
|
||||
|
||||
if (fileListBox) {
|
||||
// Desktop file list is w-64 = 256px, allow some tolerance for borders
|
||||
expect(fileListBox.width).toBeLessThanOrEqual(300);
|
||||
expect(fileListBox.width).toBeGreaterThanOrEqual(200);
|
||||
}
|
||||
});
|
||||
|
||||
test('should show action buttons inline in header on desktop', async ({ page }) => {
|
||||
await setupProjectWithFixture(page, getFixturePath());
|
||||
await authenticateForTests(page);
|
||||
|
||||
await navigateToContext(page);
|
||||
|
||||
// On desktop, inline buttons should be visible
|
||||
const createButton = page.locator('[data-testid="create-markdown-button"]');
|
||||
await expect(createButton).toBeVisible();
|
||||
|
||||
const importButton = page.locator('[data-testid="import-file-button"]');
|
||||
await expect(importButton).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user