/**
* Basic Application E2E Tests
*
* Tests fundamental application loading, UI structure, and connection handling.
*/
import { test, expect } from '@playwright/test';
import { RequestHandlerPage } from '../support/page-objects/request-handler.page';
import { ServerManager, TEST_PORTS, getAvailablePort } from '../support/test-utils/server-manager';
import { mockBrowserNotifications, waitForSSEConnection, logTestStep } from '../support/test-utils/helpers';
test.describe('Basic Application Loading', () => {
let serverManager: ServerManager;
let requestHandler: RequestHandlerPage;
test.beforeEach(async ({ page }) => {
// Mock browser notifications to prevent permission dialogs
await mockBrowserNotifications(page);
// Start MCP server with available port for each test to prevent conflicts
const availablePort = await getAvailablePort(TEST_PORTS.BASIC);
serverManager = new ServerManager({
port: availablePort,
debug: true
});
logTestStep('Starting MCP server', { port: availablePort });
await serverManager.start();
// Initialize page object
requestHandler = new RequestHandlerPage(page);
// Navigate to the application
logTestStep('Navigating to application');
await requestHandler.goto(availablePort);
});
test.afterEach(async () => {
if (serverManager) {
logTestStep('Stopping MCP server');
await serverManager.stop();
}
});
test('should load application successfully', async () => {
logTestStep('Testing application load');
// Verify basic page structure
await requestHandler.waitForLoad();
// Check header elements
await expect(requestHandler.appTitle).toHaveText('Ask Me MCP');
await expect(requestHandler.appIcon).toBeVisible();
await expect(requestHandler.connectionStatus).toBeVisible();
// Check main content area
await expect(requestHandler.mainContent).toBeVisible();
logTestStep('Application loaded successfully');
});
test('should display proper connection status', async ({ page }) => {
logTestStep('Testing connection status');
// Wait for SSE connection to be established
await waitForSSEConnection(page);
// Should show connected status
await requestHandler.waitForConnection();
expect(await requestHandler.isConnected()).toBe(true);
logTestStep('Connection status working correctly');
});
test('should display waiting message when no requests', async () => {
logTestStep('Testing waiting message display');
// Wait for connection
await requestHandler.waitForConnection();
// Should show waiting message with proper content
await expect(requestHandler.waitingMessage.locator('h2')).toContainText('Waiting for requests');
// Wait specifically for the waiting message connection info to show connected status
// This fixes the race condition where header shows connected but waiting message hasn't updated yet
await requestHandler.waitForWaitingMessageConnected();
logTestStep('Waiting message displayed correctly');
});
test('should have blueprint background', async () => {
logTestStep('Testing blueprint background');
// Check if blueprint background is applied
const hasBlueprintBg = await requestHandler.hasBlueprintBackground();
expect(hasBlueprintBg).toBe(true);
// Verify body background properties
const bodyBg = await requestHandler.page.evaluate(() => {
const body = document.querySelector('body');
const style = window.getComputedStyle(body!);
return {
backgroundColor: style.backgroundColor,
backgroundImage: style.backgroundImage
};
});
// Should have dark blue background
expect(bodyBg.backgroundColor).toContain('rgb');
logTestStep('Blueprint background verified', bodyBg);
});
test('should be responsive on different screen sizes', async () => {
logTestStep('Testing responsive design');
await requestHandler.checkResponsiveDesign();
logTestStep('Responsive design verified');
});
test('should handle server disconnection gracefully', async ({ page }) => {
logTestStep('Testing server disconnection handling');
// Wait for initial connection
await requestHandler.waitForConnection();
// Stop the server to simulate disconnection
await serverManager.stop();
// Should detect disconnection and update status
await requestHandler.waitForDisconnection();
expect(await requestHandler.isConnected()).toBe(false);
logTestStep('Server disconnection handled correctly');
});
test('should show proper favicon and page title', async ({ page }) => {
logTestStep('Testing page metadata');
// Check page title
await expect(page).toHaveTitle(/Ask Me MCP/);
// Check if favicon exists in the DOM
const faviconLink = page.locator('link[rel="icon"], link[rel="shortcut icon"]');
await expect(faviconLink).toHaveAttribute('href', /favicon\.ico/);
// Check if favicon is accessible (optional - may not work in all test environments)
try {
const faviconRequest = page.waitForRequest('**/favicon.ico', { timeout: 2000 });
await page.reload();
await faviconRequest;
logTestStep('Favicon request made');
} catch {
logTestStep('Favicon request not made (acceptable in test environment)');
}
});
test('should have proper accessibility attributes', async () => {
logTestStep('Testing accessibility attributes');
// Check for proper heading structure
const h1 = requestHandler.appTitle;
await expect(h1).toBeVisible();
// Check for proper ARIA attributes where applicable
const connectionStatus = requestHandler.connectionStatus;
await expect(connectionStatus).toBeVisible();
// Check for proper semantic HTML structure
const header = requestHandler.header;
await expect(header).toHaveRole('banner', { timeout: 5000 }).catch(() => {
// Header might not have explicit role, which is fine
logTestStep('Header role not explicitly set (acceptable)');
});
const main = requestHandler.mainContent;
await expect(main).toBeVisible();
logTestStep('Accessibility attributes verified');
});
test('should handle page refresh correctly', async ({ page }) => {
logTestStep('Testing page refresh handling');
// Wait for initial load
await requestHandler.waitForLoad();
await requestHandler.waitForConnection();
// Refresh the page
await page.reload();
// Should load correctly again
await requestHandler.waitForLoad();
await waitForSSEConnection(page);
await requestHandler.waitForConnection();
expect(await requestHandler.isConnected()).toBe(true);
logTestStep('Page refresh handled correctly');
});
});