UNPKG

@ordojs/core

Version:

Core compiler and runtime for OrdoJS framework

347 lines 11.8 kB
/** * @fileoverview Integration Testing Utilities for OrdoJS Framework */ import { JSDOM } from 'jsdom'; import { ServerMockUtils } from './server-mock.js'; import { OrdoJSTestFramework } from './test-framework.js'; /** * Integration testing utilities for full-stack OrdoJS applications */ export class IntegrationTestUtils { testFramework; serverMockUtils; jsdomInstance; currentEnvironment; testDatabaseConfig; serverConfig; constructor() { this.testFramework = new OrdoJSTestFramework(); this.serverMockUtils = new ServerMockUtils(); } /** * Set up integration test environment */ async setupTestEnvironment(config) { // Set up JSDOM environment if needed if (config.jsdom) { this.jsdomInstance = new JSDOM('<!DOCTYPE html><html><body></body></html>', { url: config.baseUrl || 'http://localhost', pretendToBeVisual: true, resources: 'usable', runScripts: 'dangerously' }); // Set up global DOM environment global.window = this.jsdomInstance.window; global.document = this.jsdomInstance.window.document; global.navigator = this.jsdomInstance.window.navigator; global.HTMLElement = this.jsdomInstance.window.HTMLElement; global.Element = this.jsdomInstance.window.Element; global.Node = this.jsdomInstance.window.Node; global.Event = this.jsdomInstance.window.Event; global.CustomEvent = this.jsdomInstance.window.CustomEvent; } // Set up test database if configured if (config.database) { this.testDatabaseConfig = config.database; await this.setupTestDatabase(config.database); } // Set up test server if configured if (config.server) { this.serverConfig = config.server; await this.setupTestServer(config.server); } // Set up server mocks if (config.serverMocks) { for (const mockConfig of config.serverMocks) { this.serverMockUtils.mockServerFunction(mockConfig.functionName, mockConfig.implementation, mockConfig); } } this.currentEnvironment = { jsdom: config.jsdom, node: true, browser: config.jsdom, globals: config.globals }; // Set up global variables if (config.globals) { Object.assign(global, config.globals); } } /** * Set up test database */ async setupTestDatabase(config) { // This would be implemented based on the database type // For now, just log that we would set up a database console.log(`Setting up test database: ${config.type}`); } /** * Set up test server */ async setupTestServer(config) { // This would be implemented based on the server configuration // For now, just log that we would set up a server console.log(`Setting up test server on port: ${config.port || 3000}`); } /** * Clean up test environment */ async teardownTestEnvironment() { // Clean up JSDOM if (this.jsdomInstance) { this.jsdomInstance.window.close(); this.jsdomInstance = undefined; // Clean up globals delete global.window; delete global.document; delete global.navigator; delete global.HTMLElement; delete global.Element; delete global.Node; delete global.Event; delete global.CustomEvent; } // Clean up test database if (this.testDatabaseConfig) { await this.teardownTestDatabase(); this.testDatabaseConfig = undefined; } // Clean up test server if (this.serverConfig) { await this.teardownTestServer(); this.serverConfig = undefined; } // Clean up server mocks this.serverMockUtils.removeAllMocks(); // Clean up global variables if (this.currentEnvironment?.globals) { for (const key of Object.keys(this.currentEnvironment.globals)) { delete global[key]; } } this.currentEnvironment = undefined; } /** * Clean up test database */ async teardownTestDatabase() { // This would be implemented based on the database type // For now, just log that we would tear down a database console.log('Tearing down test database'); } /** * Clean up test server */ async teardownTestServer() { // This would be implemented based on the server configuration // For now, just log that we would tear down a server console.log('Tearing down test server'); } /** * Run integration test */ async runIntegrationTest(testFn, config) { const startTime = performance.now(); const errors = []; const warnings = []; try { // Set up test environment await this.setupTestEnvironment(config); // Run the test function await testFn(); const duration = performance.now() - startTime; return { success: true, errors, warnings, duration, metadata: { environment: this.currentEnvironment } }; } catch (error) { const duration = performance.now() - startTime; errors.push(error instanceof Error ? error.message : String(error)); return { success: false, errors, warnings, duration, metadata: { environment: this.currentEnvironment } }; } finally { // Clean up test environment await this.teardownTestEnvironment(); } } /** * Run multiple integration tests */ async runIntegrationTests(tests, baseConfig) { const results = []; for (const test of tests) { const config = { ...baseConfig, ...test.config }; const result = await this.runIntegrationTest(test.testFn, config); result.name = test.name; results.push(result); } return results; } /** * Get test framework instance */ getTestFramework() { return this.testFramework; } /** * Get server mock utils instance */ getServerMockUtils() { return this.serverMockUtils; } /** * Create a mock server function */ mockServerFunction(functionName, implementation, config = {}) { this.serverMockUtils.mockServerFunction(functionName, implementation, config); } /** * Navigate to a URL in the JSDOM environment */ async navigateTo(url) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } // This is a simplified implementation // In a real implementation, we would use JSDOM's navigation capabilities await new Promise((resolve) => { // Make sure the URL is absolute const baseUrl = this.jsdomInstance.window.location.origin; const fullUrl = new URL(url, baseUrl).toString(); this.jsdomInstance.reconfigure({ url: fullUrl }); setTimeout(resolve, 100); // Give time for any scripts to load }); } /** * Wait for an element to appear in the DOM */ async waitForElement(selector, timeout = 5000) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } const startTime = Date.now(); while (Date.now() - startTime < timeout) { const element = document.querySelector(selector); if (element) { return element; } await new Promise(resolve => setTimeout(resolve, 50)); } throw new Error(`Element not found: ${selector} (timeout: ${timeout}ms)`); } /** * Wait for a condition to be true */ async waitForCondition(condition, timeout = 5000, interval = 50) { const startTime = Date.now(); while (Date.now() - startTime < timeout) { const result = await condition(); if (result) { return; } await new Promise(resolve => setTimeout(resolve, interval)); } throw new Error(`Condition not met within timeout: ${timeout}ms`); } /** * Fill a form field */ async fillFormField(selector, value) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } const element = document.querySelector(selector); if (!element) { throw new Error(`Form field not found: ${selector}`); } if (element instanceof this.jsdomInstance.window.HTMLInputElement || element instanceof this.jsdomInstance.window.HTMLTextAreaElement || element instanceof this.jsdomInstance.window.HTMLSelectElement) { // Set the value element.value = value; // Dispatch input event const inputEvent = new this.jsdomInstance.window.Event('input', { bubbles: true }); element.dispatchEvent(inputEvent); // Dispatch change event const changeEvent = new this.jsdomInstance.window.Event('change', { bubbles: true }); element.dispatchEvent(changeEvent); } else { throw new Error(`Element is not a form field: ${selector}`); } } /** * Click an element */ async clickElement(selector) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } const element = document.querySelector(selector); if (!element) { throw new Error(`Element not found: ${selector}`); } // Dispatch click event const clickEvent = new this.jsdomInstance.window.Event('click', { bubbles: true }); element.dispatchEvent(clickEvent); } /** * Get element text content */ getElementText(selector) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } const element = document.querySelector(selector); if (!element) { throw new Error(`Element not found: ${selector}`); } return element.textContent || ''; } /** * Get element attribute */ getElementAttribute(selector, attribute) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } const element = document.querySelector(selector); if (!element) { throw new Error(`Element not found: ${selector}`); } return element.getAttribute(attribute); } /** * Check if element exists */ elementExists(selector) { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } return document.querySelector(selector) !== null; } /** * Get current URL */ getCurrentUrl() { if (!this.jsdomInstance) { throw new Error('JSDOM environment not set up'); } return this.jsdomInstance.window.location.href; } } //# sourceMappingURL=integration-test.js.map