201 lines
6.0 KiB
TypeScript
201 lines
6.0 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Frontend Logging System', () => {
|
|
let logRequests: any[] = [];
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
logRequests = [];
|
|
|
|
// Intercept log requests
|
|
await page.route('**/api/log', async (route) => {
|
|
const request = route.request();
|
|
const postData = request.postDataJSON();
|
|
|
|
// Store the log data
|
|
if (Array.isArray(postData)) {
|
|
logRequests.push(...postData);
|
|
} else {
|
|
logRequests.push(postData);
|
|
}
|
|
|
|
// Respond with success
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ ok: true }),
|
|
});
|
|
});
|
|
});
|
|
|
|
test('should log APP_START on page load', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Wait for logs to be sent
|
|
await page.waitForTimeout(3000);
|
|
|
|
const appStartLogs = logRequests.filter(log => log.event === 'APP_START');
|
|
expect(appStartLogs.length).toBeGreaterThan(0);
|
|
|
|
const log = appStartLogs[0];
|
|
expect(log.app).toBe('ObsiViewer');
|
|
expect(log.sessionId).toBeTruthy();
|
|
expect(log.context).toBeDefined();
|
|
});
|
|
|
|
test('should log SEARCH_EXECUTED on search', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Find search input and perform search
|
|
const searchInput = page.locator('input[type="search"], input[placeholder*="search" i]').first();
|
|
await searchInput.fill('test query');
|
|
await searchInput.press('Enter');
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
const searchLogs = logRequests.filter(log => log.event === 'SEARCH_EXECUTED');
|
|
expect(searchLogs.length).toBeGreaterThan(0);
|
|
|
|
const log = searchLogs[0];
|
|
expect(log.data.query).toBe('test query');
|
|
});
|
|
|
|
test('should log BOOKMARKS_OPEN when opening bookmarks', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Click bookmarks button/tab
|
|
const bookmarksButton = page.locator('button:has-text("Bookmarks"), [data-testid="bookmarks-tab"]').first();
|
|
if (await bookmarksButton.isVisible()) {
|
|
await bookmarksButton.click();
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
const bookmarksLogs = logRequests.filter(log => log.event === 'BOOKMARKS_OPEN');
|
|
expect(bookmarksLogs.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
test('should log GRAPH_VIEW_OPEN when opening graph view', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Click graph view button/tab
|
|
const graphButton = page.locator('button:has-text("Graph"), [data-testid="graph-tab"]').first();
|
|
if (await graphButton.isVisible()) {
|
|
await graphButton.click();
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
const graphLogs = logRequests.filter(log => log.event === 'GRAPH_VIEW_OPEN');
|
|
expect(graphLogs.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
test('should log THEME_CHANGE when toggling theme', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Find and click theme toggle button
|
|
const themeButton = page.locator('button[aria-label*="theme" i], button:has-text("Theme")').first();
|
|
if (await themeButton.isVisible()) {
|
|
await themeButton.click();
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
const themeLogs = logRequests.filter(log => log.event === 'THEME_CHANGE');
|
|
expect(themeLogs.length).toBeGreaterThan(0);
|
|
|
|
const log = themeLogs[0];
|
|
expect(log.data.from).toBeDefined();
|
|
expect(log.data.to).toBeDefined();
|
|
}
|
|
});
|
|
|
|
test('should include session ID in all logs', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Perform multiple actions
|
|
const searchInput = page.locator('input[type="search"]').first();
|
|
if (await searchInput.isVisible()) {
|
|
await searchInput.fill('test');
|
|
await searchInput.press('Enter');
|
|
}
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
expect(logRequests.length).toBeGreaterThan(0);
|
|
|
|
const sessionIds = new Set(logRequests.map(log => log.sessionId));
|
|
expect(sessionIds.size).toBe(1); // All logs should have same session ID
|
|
});
|
|
|
|
test('should include context in all logs', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Wait for logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
expect(logRequests.length).toBeGreaterThan(0);
|
|
|
|
logRequests.forEach(log => {
|
|
expect(log.context).toBeDefined();
|
|
expect(log.context.version).toBeDefined();
|
|
expect(log.context.route).toBeDefined();
|
|
});
|
|
});
|
|
|
|
test('should batch logs when multiple events occur', async ({ page }) => {
|
|
await page.goto('/');
|
|
|
|
// Perform multiple quick actions
|
|
const searchInput = page.locator('input[type="search"]').first();
|
|
if (await searchInput.isVisible()) {
|
|
await searchInput.fill('test1');
|
|
await searchInput.press('Enter');
|
|
await page.waitForTimeout(100);
|
|
|
|
await searchInput.fill('test2');
|
|
await searchInput.press('Enter');
|
|
await page.waitForTimeout(100);
|
|
|
|
await searchInput.fill('test3');
|
|
await searchInput.press('Enter');
|
|
}
|
|
|
|
// Wait for batched logs
|
|
await page.waitForTimeout(3000);
|
|
|
|
// Should have received logs (possibly batched)
|
|
expect(logRequests.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
test('should handle offline scenario', async ({ page, context }) => {
|
|
await page.goto('/');
|
|
|
|
// Go offline
|
|
await context.setOffline(true);
|
|
|
|
// Perform actions while offline
|
|
const searchInput = page.locator('input[type="search"]').first();
|
|
if (await searchInput.isVisible()) {
|
|
await searchInput.fill('offline test');
|
|
await searchInput.press('Enter');
|
|
}
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
const offlineLogCount = logRequests.length;
|
|
|
|
// Go back online
|
|
await context.setOffline(false);
|
|
|
|
// Wait for queued logs to be sent
|
|
await page.waitForTimeout(5000);
|
|
|
|
// Should have received more logs after going online
|
|
expect(logRequests.length).toBeGreaterThanOrEqual(offlineLogCount);
|
|
});
|
|
});
|