@ordojs/core
Version:
Core compiler and runtime for OrdoJS framework
347 lines • 11.8 kB
JavaScript
/**
* @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