UNPKG

@nestjsvn/swagger-sse

Version:

OpenAPI documentation and interactive Swagger UI for NestJS Server-Sent Events endpoints

210 lines (209 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const setup_1 = require("./setup"); const test_controllers_1 = require("./test-controllers"); describe('Cross-Browser Compatibility E2E Tests', () => { const browsers = ['chromium', 'firefox', 'webkit']; describe.each(browsers)('Browser: %s', browserType => { let context; beforeAll(async () => { context = await setup_1.E2ETestSetup.createContext(`cross-browser-${browserType}`, { controllers: [test_controllers_1.TestEventsController], }, browserType); }); afterAll(async () => { await setup_1.E2ETestSetup.cleanup(`cross-browser-${browserType}`); }); it('should load Swagger UI correctly', async () => { await context.page.goto(`${context.baseUrl}/api-docs`); // Wait for Swagger UI to load await context.page.waitForSelector('.swagger-ui', { timeout: 10000 }); // Verify basic UI elements are present const title = await context.page.textContent('h2.title'); expect(title).toContain('Test API'); // Check for SSE endpoints const endpoints = await context.page.$$('[data-path*="/test-events"]'); expect(endpoints.length).toBeGreaterThan(0); }); it('should establish SSE connections', async () => { await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); await context.page.click('[data-path="/test-events/basic"] .opblock-summary'); // Test SSE connection await setup_1.SSETestHelpers.connectToSSE(context.page); const status = await context.page.getAttribute('[data-testid="sse-status"]', 'data-status'); expect(status).toBe('connected'); }); it('should receive and display events', async () => { await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); await context.page.click('[data-path="/test-events/basic"] .opblock-summary'); await setup_1.SSETestHelpers.connectToSSE(context.page); await setup_1.SSETestHelpers.waitForSSEEvents(context.page, 1, 10000); const events = await setup_1.SSETestHelpers.getSSEEvents(context.page); expect(events.length).toBeGreaterThan(0); }); it('should handle EventSource API correctly', async () => { await context.page.goto(`${context.baseUrl}/api-docs`); // Check if EventSource is available const hasEventSource = await context.page.evaluate(() => { return typeof EventSource !== 'undefined'; }); expect(hasEventSource).toBe(true); // Test EventSource functionality const eventSourceWorks = await context.page.evaluate(() => { try { const es = new EventSource('data:text/plain,'); es.close(); return true; } catch (error) { return false; } }); expect(eventSourceWorks).toBe(true); }); it('should handle CSS and styling correctly', async () => { await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); // Check if SSE plugin CSS is loaded const _hasSSEStyles = await context.page.evaluate(() => { const stylesheets = Array.from(document.styleSheets); return stylesheets.some(sheet => { try { const rules = Array.from(sheet.cssRules || []); return rules.some(rule => rule.cssText && rule.cssText.includes('sse-')); } catch { return false; } }); }); // Note: This might be false if CSS is inlined, which is acceptable // The important thing is that the UI renders correctly const uiRendered = (await context.page.$('.swagger-ui')) !== null; expect(uiRendered).toBe(true); }); }); describe('Browser-Specific Features', () => { it('should work with Chrome DevTools Protocol', async () => { const context = await setup_1.E2ETestSetup.createContext('chrome-devtools', { controllers: [test_controllers_1.TestEventsController] }, 'chromium'); try { // Enable network domain for monitoring const client = await context.page.context().newCDPSession(context.page); await client.send('Network.enable'); await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); await context.page.click('[data-path="/test-events/basic"] .opblock-summary'); // Monitor network requests const networkRequests = []; client.on('Network.requestWillBeSent', (params) => { networkRequests.push(params); }); await setup_1.SSETestHelpers.connectToSSE(context.page); // Wait a bit for network activity await context.page.waitForTimeout(2000); // Should have SSE connection request const sseRequest = networkRequests.find(req => req.request.url.includes('/test-events/basic')); expect(sseRequest).toBeDefined(); } finally { await setup_1.E2ETestSetup.cleanup('chrome-devtools'); } }); it('should handle Firefox-specific EventSource behavior', async () => { const context = await setup_1.E2ETestSetup.createContext('firefox-specific', { controllers: [test_controllers_1.TestEventsController] }, 'firefox'); try { await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); await context.page.click('[data-path="/test-events/basic"] .opblock-summary'); // Firefox has specific EventSource implementation details const firefoxEventSourceFeatures = await context.page.evaluate(() => { const es = new EventSource('data:text/plain,'); const features = { hasReadyState: 'readyState' in es, hasUrl: 'url' in es, hasWithCredentials: 'withCredentials' in es, }; es.close(); return features; }); expect(firefoxEventSourceFeatures.hasReadyState).toBe(true); expect(firefoxEventSourceFeatures.hasUrl).toBe(true); } finally { await setup_1.E2ETestSetup.cleanup('firefox-specific'); } }); it('should handle Safari/WebKit-specific behavior', async () => { const context = await setup_1.E2ETestSetup.createContext('webkit-specific', { controllers: [test_controllers_1.TestEventsController] }, 'webkit'); try { await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); // WebKit has specific handling for CORS and EventSource const webkitFeatures = await context.page.evaluate(() => { return { userAgent: navigator.userAgent, hasEventSource: typeof EventSource !== 'undefined', supportsCORS: 'withCredentials' in new XMLHttpRequest(), }; }); expect(webkitFeatures.hasEventSource).toBe(true); expect(webkitFeatures.supportsCORS).toBe(true); } finally { await setup_1.E2ETestSetup.cleanup('webkit-specific'); } }); }); describe('Responsive Design and Mobile', () => { it('should work on mobile viewport sizes', async () => { const context = await setup_1.E2ETestSetup.createContext('mobile-responsive', { controllers: [test_controllers_1.TestEventsController], }); try { // Set mobile viewport await context.page.setViewportSize({ width: 375, height: 667 }); await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); // Check if UI is responsive const isResponsive = await context.page.evaluate(() => { const swaggerUI = document.querySelector('.swagger-ui'); if (!swaggerUI) return false; const rect = swaggerUI.getBoundingClientRect(); return rect.width <= window.innerWidth; }); expect(isResponsive).toBe(true); // Test SSE functionality on mobile await context.page.click('[data-path="/test-events/basic"] .opblock-summary'); await setup_1.SSETestHelpers.connectToSSE(context.page); const status = await context.page.getAttribute('[data-testid="sse-status"]', 'data-status'); expect(status).toBe('connected'); } finally { await setup_1.E2ETestSetup.cleanup('mobile-responsive'); } }); it('should handle touch interactions', async () => { const context = await setup_1.E2ETestSetup.createContext('touch-interactions', { controllers: [test_controllers_1.TestEventsController], }); try { // Enable touch events await context.page.setViewportSize({ width: 375, height: 667 }); await context.page.goto(`${context.baseUrl}/api-docs`); await context.page.waitForSelector('.swagger-ui'); // Use tap instead of click for mobile await context.page.tap('[data-path="/test-events/basic"] .opblock-summary'); await context.page.tap('[data-testid="sse-connect-btn"]'); await context.page.waitForSelector('[data-testid="sse-status"][data-status="connected"]'); const status = await context.page.getAttribute('[data-testid="sse-status"]', 'data-status'); expect(status).toBe('connected'); } finally { await setup_1.E2ETestSetup.cleanup('touch-interactions'); } }); }); });