mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
- Implemented E2E tests for code relationship visualization in Graph Explorer. - Added tests for archived session management in History, including search, filter, restore, and delete functionalities. - Created tests for workflow orchestration in Orchestrator, covering node creation, connection, deletion, and workflow management. - Developed tests for project statistics and timeline visualization in Project, including error handling and internationalization checks.
357 lines
11 KiB
TypeScript
357 lines
11 KiB
TypeScript
// ========================================
|
|
// E2E Tests: History - Archived Session Management
|
|
// ========================================
|
|
// End-to-end tests for history page with search, filter, restore operations
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import { setupEnhancedMonitoring, switchLanguageAndVerify } from './helpers/i18n-helpers';
|
|
|
|
test.describe('[History] - Archived Session Management Tests', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/history', { waitUntil: 'networkidle' as const });
|
|
});
|
|
|
|
test('L3.31 - Page loads and displays archived sessions', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for history
|
|
await page.route('**/api/history', (route) => {
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
sessions: [
|
|
{
|
|
id: 'session-1',
|
|
title: 'Archived Session 1',
|
|
archivedAt: Date.now(),
|
|
status: 'completed'
|
|
}
|
|
]
|
|
})
|
|
});
|
|
});
|
|
|
|
// Reload to trigger API
|
|
await page.reload({ waitUntil: 'networkidle' as const });
|
|
|
|
// Look for history list
|
|
const historyList = page.getByTestId('history-list').or(
|
|
page.locator('.history-list')
|
|
);
|
|
|
|
const isListVisible = await historyList.isVisible().catch(() => false);
|
|
|
|
if (isListVisible) {
|
|
// Verify session items are displayed
|
|
const sessionItems = page.getByTestId(/session-item|history-item/).or(
|
|
page.locator('.history-item')
|
|
);
|
|
|
|
const itemCount = await sessionItems.count();
|
|
expect(itemCount).toBeGreaterThanOrEqual(0);
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.32 - Search archived sessions', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for search
|
|
await page.route('**/api/history?q=**', (route) => {
|
|
const requestUrl = route.request().url();
|
|
const url = new URL(requestUrl);
|
|
const query = url.searchParams.get('q');
|
|
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
sessions: [
|
|
{
|
|
id: 'session-search',
|
|
title: `Search Result for ${query}`,
|
|
archivedAt: Date.now()
|
|
}
|
|
]
|
|
})
|
|
});
|
|
});
|
|
|
|
// Look for search input
|
|
const searchInput = page.getByRole('textbox', { name: /search|find/i }).or(
|
|
page.getByTestId('search-input')
|
|
);
|
|
|
|
const hasSearchInput = await searchInput.isVisible().catch(() => false);
|
|
|
|
if (hasSearchInput) {
|
|
await searchInput.fill('test');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Verify search was performed
|
|
const searchResults = page.getByTestId(/history-item|session-item/);
|
|
const resultCount = await searchResults.count();
|
|
expect(resultCount).toBeGreaterThanOrEqual(0);
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.33 - Filter by date range', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for date filter
|
|
await page.route('**/api/history**', (route) => {
|
|
const requestUrl = route.request().url();
|
|
const url = new URL(requestUrl);
|
|
const fromDate = url.searchParams.get('from');
|
|
const toDate = url.searchParams.get('to');
|
|
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
sessions: [
|
|
{
|
|
id: 'session-filtered',
|
|
title: 'Filtered by Date',
|
|
archivedAt: Date.now()
|
|
}
|
|
]
|
|
})
|
|
});
|
|
});
|
|
|
|
// Look for date filter controls
|
|
const dateFilter = page.getByTestId('date-filter').or(
|
|
page.locator('*').filter({ hasText: /date|filter/i })
|
|
);
|
|
|
|
const hasDateFilter = await dateFilter.isVisible().catch(() => false);
|
|
|
|
if (hasDateFilter) {
|
|
const fromDateInput = page.getByRole('textbox', { name: /from|start/i });
|
|
const hasFromDate = await fromDateInput.isVisible().catch(() => false);
|
|
|
|
if (hasFromDate) {
|
|
await fromDateInput.fill('2024-01-01');
|
|
|
|
const toDateInput = page.getByRole('textbox', { name: /to|end/i });
|
|
const hasToDate = await toDateInput.isVisible().catch(() => false);
|
|
|
|
if (hasToDate) {
|
|
await toDateInput.fill('2024-12-31');
|
|
|
|
// Look for apply button
|
|
const applyButton = page.getByRole('button', { name: /apply|filter/i });
|
|
const hasApplyButton = await applyButton.isVisible().catch(() => false);
|
|
|
|
if (hasApplyButton) {
|
|
await applyButton.click();
|
|
await page.waitForTimeout(500);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.34 - Restore archived session', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for restore
|
|
await page.route('**/api/history/*/restore', (route) => {
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ success: true, sessionId: 'restored-session' })
|
|
});
|
|
});
|
|
|
|
// Look for archived session
|
|
const sessionItems = page.getByTestId(/session-item|history-item/).or(
|
|
page.locator('.history-item')
|
|
);
|
|
|
|
const itemCount = await sessionItems.count();
|
|
|
|
if (itemCount > 0) {
|
|
const firstSession = sessionItems.first();
|
|
|
|
// Look for restore button
|
|
const restoreButton = firstSession.getByRole('button', { name: /restore|reload/i }).or(
|
|
firstSession.getByTestId('restore-button')
|
|
);
|
|
|
|
const hasRestoreButton = await restoreButton.isVisible().catch(() => false);
|
|
|
|
if (hasRestoreButton) {
|
|
await restoreButton.click();
|
|
|
|
// Verify success message
|
|
const successMessage = page.getByText(/restored|success/i);
|
|
const hasSuccess = await successMessage.isVisible().catch(() => false);
|
|
expect(hasSuccess).toBe(true);
|
|
}
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.35 - Delete archived session', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for delete
|
|
await page.route('**/api/history/*', (route) => {
|
|
if (route.request().method() === 'DELETE') {
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ success: true })
|
|
});
|
|
} else {
|
|
route.continue();
|
|
}
|
|
});
|
|
|
|
// Look for archived session
|
|
const sessionItems = page.getByTestId(/session-item|history-item/).or(
|
|
page.locator('.history-item')
|
|
);
|
|
|
|
const itemCount = await sessionItems.count();
|
|
|
|
if (itemCount > 0) {
|
|
const firstSession = sessionItems.first();
|
|
|
|
// Look for delete button
|
|
const deleteButton = firstSession.getByRole('button', { name: /delete|remove/i }).or(
|
|
firstSession.getByTestId('delete-button')
|
|
);
|
|
|
|
const hasDeleteButton = await deleteButton.isVisible().catch(() => false);
|
|
|
|
if (hasDeleteButton) {
|
|
await deleteButton.click();
|
|
|
|
// Confirm deletion if dialog appears
|
|
const confirmDialog = page.getByRole('dialog').filter({ hasText: /delete|confirm/i });
|
|
const hasDialog = await confirmDialog.isVisible().catch(() => false);
|
|
|
|
if (hasDialog) {
|
|
const confirmButton = confirmDialog.getByRole('button', { name: /delete|confirm|yes/i });
|
|
await confirmButton.click();
|
|
}
|
|
|
|
// Verify success message
|
|
const successMessage = page.getByText(/deleted|success/i);
|
|
const hasSuccess = await successMessage.isVisible().catch(() => false);
|
|
expect(hasSuccess).toBe(true);
|
|
}
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.36 - i18n - Archive messages in EN/ZH', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Get language switcher
|
|
const languageSwitcher = page.getByRole('combobox', { name: /select language|language/i }).first();
|
|
|
|
const hasLanguageSwitcher = await languageSwitcher.isVisible().catch(() => false);
|
|
|
|
if (hasLanguageSwitcher) {
|
|
// Switch to Chinese
|
|
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
|
|
|
|
// Verify history content is in Chinese
|
|
const pageContent = await page.content();
|
|
const hasChineseText = /[\u4e00-\u9fa5]/.test(pageContent);
|
|
expect(hasChineseText).toBe(true);
|
|
|
|
// Switch back to English
|
|
await switchLanguageAndVerify(page, 'en', languageSwitcher);
|
|
}
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.37 - Error - Restore fails', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API error for restore
|
|
await page.route('**/api/history/*/restore', (route) => {
|
|
route.fulfill({
|
|
status: 500,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ error: 'Failed to restore session' })
|
|
});
|
|
});
|
|
|
|
// Look for archived session
|
|
const sessionItems = page.getByTestId(/session-item|history-item/).or(
|
|
page.locator('.history-item')
|
|
);
|
|
|
|
const itemCount = await sessionItems.count();
|
|
|
|
if (itemCount > 0) {
|
|
const firstSession = sessionItems.first();
|
|
|
|
// Look for restore button
|
|
const restoreButton = firstSession.getByRole('button', { name: /restore|reload/i });
|
|
|
|
const hasRestoreButton = await restoreButton.isVisible().catch(() => false);
|
|
|
|
if (hasRestoreButton) {
|
|
await restoreButton.click();
|
|
|
|
// Verify error message
|
|
const errorMessage = page.getByText(/error|failed|unable/i);
|
|
const hasError = await errorMessage.isVisible().catch(() => false);
|
|
expect(hasError).toBe(true);
|
|
}
|
|
}
|
|
|
|
monitoring.assertClean({ ignoreAPIPatterns: ['/api/history'], allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
|
|
test('L3.38 - Edge - Empty archive state', async ({ page }) => {
|
|
const monitoring = setupEnhancedMonitoring(page);
|
|
|
|
// Mock API for empty history
|
|
await page.route('**/api/history', (route) => {
|
|
route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ sessions: [] })
|
|
});
|
|
});
|
|
|
|
// Reload to trigger API
|
|
await page.reload({ waitUntil: 'networkidle' as const });
|
|
|
|
// Look for empty state
|
|
const emptyState = page.getByTestId('empty-state').or(
|
|
page.getByText(/no history|empty|no sessions/i)
|
|
);
|
|
|
|
const hasEmptyState = await emptyState.isVisible().catch(() => false);
|
|
expect(hasEmptyState).toBe(true);
|
|
|
|
monitoring.assertClean({ allowWarnings: true });
|
|
monitoring.stop();
|
|
});
|
|
});
|