super-pancake-automation
Version:
A lightweight DOM-based UI automation framework using Chrome DevTools Protocol
479 lines (374 loc) • 17.7 kB
JavaScript
import { describe, it, beforeAll, afterAll } from 'vitest';
import {
// Test environment setup
createTestEnvironment,
cleanupTestEnvironment,
// DOM operations (v2 API)
enableDOM,
navigateTo,
// All assertion functions from assert.js
assertEqual,
assertNotEqual,
assertDeepEqual,
assertExists,
assertNotExists,
assertTrue,
assertFalse,
assertContainsText,
assertNotContainsText,
assertGreaterThan,
assertGreaterThanOrEqual,
assertLessThan,
assertLessThanOrEqual,
assertTypeOf,
assertInstanceOf,
assertArrayIncludes,
assertArrayNotIncludes,
assertLength,
assertMatch,
assertNotMatch,
assertInRange,
assertEmpty,
assertNotEmpty,
assertThrows,
// Reporting
writeReport
} from 'super-pancake-automation';
// Get project config function
async function getProjectConfig() {
try {
const fs = await import('fs');
const configPath = './super-pancake.config.js';
if (fs.existsSync(configPath)) {
const config = await import('./super-pancake.config.js');
return config.default || config;
}
} catch (error) {
console.warn('Could not load project config, using defaults');
}
return {};
}
const projectName = process.env.PROJECT_NAME || 'Super Pancake Project';
let testEnv;
describe(`${projectName} Assertion Validation Tests`, () => {
beforeAll(async () => {
console.log(`Setting up ${projectName} assertion validation tests...`);
const config = await getProjectConfig();
const isHeadless = config.headless !== false; // default to headless
testEnv = await createTestEnvironment({
headed: !isHeadless,
port: 9224, // Use different port to avoid conflicts
testName: `${projectName} Assertion Tests`
});
// Enable DOM operations once for all tests
await enableDOM();
console.log('Test environment ready');
});
afterAll(async () => {
console.log(`Cleaning up ${projectName} assertion test environment...`);
await cleanupTestEnvironment(testEnv, `${projectName} Assertion Tests`);
await writeReport();
console.log('Assertion validation test report generated');
});
it('should test assertEqual assertion', async () => {
console.log('Testing assertEqual assertions...');
// Test equal strings
assertEqual('hello', 'hello', 'Strings should be equal');
// Test equal numbers
assertEqual(42, 42, 'Numbers should be equal');
// Test equal booleans
assertEqual(true, true, 'Booleans should be equal');
// Test equal null values
assertEqual(null, null, 'Null values should be equal');
console.log('assertEqual tests passed');
});
it('should test assertNotEqual assertion', async () => {
console.log('Testing assertNotEqual assertions...');
// Test different strings
assertNotEqual('hello', 'world', 'Strings should not be equal');
// Test different numbers
assertNotEqual(42, 43, 'Numbers should not be equal');
// Test different types
assertNotEqual('42', 42, 'String and number should not be equal');
// Test null vs undefined
assertNotEqual(null, undefined, 'Null and undefined should not be equal');
console.log('assertNotEqual tests passed');
});
it('should test assertDeepEqual assertion', async () => {
console.log('Testing assertDeepEqual assertions...');
// Test equal objects
const obj1 = { name: 'John', age: 30, hobbies: ['reading', 'coding'] };
const obj2 = { name: 'John', age: 30, hobbies: ['reading', 'coding'] };
assertDeepEqual(obj1, obj2, 'Objects should be deeply equal');
// Test equal arrays
const arr1 = [1, 2, 3, { x: 10 }];
const arr2 = [1, 2, 3, { x: 10 }];
assertDeepEqual(arr1, arr2, 'Arrays should be deeply equal');
// Test equal nested structures
const nested1 = { user: { profile: { settings: { theme: 'dark' } } } };
const nested2 = { user: { profile: { settings: { theme: 'dark' } } } };
assertDeepEqual(nested1, nested2, 'Nested objects should be deeply equal');
console.log('assertDeepEqual tests passed');
});
it('should test assertExists and assertNotExists assertions', async () => {
console.log('Testing existence assertions...');
// Test values that exist
assertExists('hello', 'String should exist');
assertExists(0, 'Zero should exist');
assertExists(false, 'False should exist');
assertExists([], 'Empty array should exist');
assertExists({}, 'Empty object should exist');
// Test values that don't exist
assertNotExists(null, 'Null should not exist');
assertNotExists(undefined, 'Undefined should not exist');
console.log('Existence assertion tests passed');
});
it('should test assertTrue and assertFalse assertions', async () => {
console.log('Testing boolean assertions...');
// Test true conditions
assertTrue(true, 'True literal should be true');
assertTrue(1 === 1, 'Equality should be true');
assertTrue('hello'.length > 0, 'String length should be greater than 0');
assertTrue([1, 2, 3].includes(2), 'Array should include element');
// Test false conditions
assertFalse(false, 'False literal should be false');
assertFalse(1 === 2, 'Inequality should be false');
assertFalse(''.length > 0, 'Empty string length should not be greater than 0');
assertFalse([1, 2, 3].includes(4), 'Array should not include element');
console.log('Boolean assertion tests passed');
});
it('should test text content assertions', async () => {
console.log('Testing text content assertions...');
const sampleText = 'The quick brown fox jumps over the lazy dog';
// Test text contains
assertContainsText(sampleText, 'quick', 'Text should contain quick');
assertContainsText(sampleText, 'fox', 'Text should contain fox');
assertContainsText(sampleText, 'lazy dog', 'Text should contain lazy dog');
// Test text does not contain
assertNotContainsText(sampleText, 'elephant', 'Text should not contain elephant');
assertNotContainsText(sampleText, 'QUICK', 'Text should not contain QUICK');
assertNotContainsText(sampleText, 'xyz', 'Text should not contain xyz');
console.log('Text content assertion tests passed');
});
it('should test numeric comparison assertions', async () => {
console.log('Testing numeric comparison assertions...');
const value = 50;
// Test greater than
assertGreaterThan(value, 49, '50 should be greater than 49');
assertGreaterThan(100, 50, '100 should be greater than 50');
// Test greater than or equal
assertGreaterThanOrEqual(value, 50, '50 should be greater than or equal to 50');
assertGreaterThanOrEqual(value, 49, '50 should be greater than or equal to 49');
// Test less than
assertLessThan(value, 51, '50 should be less than 51');
assertLessThan(25, 50, '25 should be less than 50');
// Test less than or equal
assertLessThanOrEqual(value, 50, '50 should be less than or equal to 50');
assertLessThanOrEqual(value, 51, '50 should be less than or equal to 51');
console.log('Numeric comparison assertion tests passed');
});
it('should test type validation assertions', async () => {
console.log('Testing type validation assertions...');
// Test typeof assertions
assertTypeOf('hello', 'string', 'Should be string type');
assertTypeOf(42, 'number', 'Should be number type');
assertTypeOf(true, 'boolean', 'Should be boolean type');
assertTypeOf(undefined, 'undefined', 'Should be undefined type');
assertTypeOf({}, 'object', 'Should be object type');
assertTypeOf([], 'object', 'Array should be object type');
assertTypeOf(() => {}, 'function', 'Should be function type');
// Test instanceof assertions
assertInstanceOf(new Date(), Date, 'Should be instance of Date');
assertInstanceOf([], Array, 'Should be instance of Array');
assertInstanceOf({}, Object, 'Should be instance of Object');
assertInstanceOf(new Error('test'), Error, 'Should be instance of Error');
console.log('Type validation assertion tests passed');
});
it('should test array validation assertions', async () => {
console.log('Testing array validation assertions...');
const fruits = ['apple', 'banana', 'orange', 'grape'];
const numbers = [1, 2, 3, 4, 5];
// Test array includes
assertArrayIncludes(fruits, 'apple', 'Array should include apple');
assertArrayIncludes(fruits, 'banana', 'Array should include banana');
assertArrayIncludes(numbers, 3, 'Array should include number 3');
// Test array does not include
assertArrayNotIncludes(fruits, 'pineapple', 'Array should not include pineapple');
assertArrayNotIncludes(fruits, 'kiwi', 'Array should not include kiwi');
assertArrayNotIncludes(numbers, 10, 'Array should not include number 10');
// Test array length
assertLength(fruits, 4, 'Fruits array should have length 4');
assertLength(numbers, 5, 'Numbers array should have length 5');
assertLength('hello', 5, 'String should have length 5');
assertLength('', 0, 'Empty string should have length 0');
console.log('Array validation assertion tests passed');
});
it('should test regex pattern assertions', async () => {
console.log('Testing regex pattern assertions...');
const email = 'user@example.com';
const phone = '123-456-7890';
const invalidEmail = 'invalid-email';
// Test regex matches
assertMatch(email, /^[^@]+@[^@]+\.[^@]+$/, 'Should match email pattern');
assertMatch(phone, /^\d{3}-\d{3}-\d{4}$/, 'Should match phone number pattern');
assertMatch('Hello123', /^[A-Za-z0-9]+$/, 'Should match alphanumeric pattern');
// Test regex does not match
assertNotMatch(invalidEmail, /^[^@]+@[^@]+\.[^@]+$/, 'Should not match email pattern');
assertNotMatch('hello world', /^\d+$/, 'Should not match digits only pattern');
assertNotMatch('ABC', /^[a-z]+$/, 'Should not match lowercase only pattern');
console.log('Regex pattern assertion tests passed');
});
it('should test range and boundary assertions', async () => {
console.log('Testing range and boundary assertions...');
// Test in range
assertInRange(5, 1, 10, '5 should be in range 1-10');
assertInRange(50, 0, 100, '50 should be in range 0-100');
assertInRange(-5, -10, 0, '-5 should be in range -10 to 0');
// Test boundary values
assertInRange(1, 1, 10, '1 should be in range 1-10 (lower boundary)');
assertInRange(10, 1, 10, '10 should be in range 1-10 (upper boundary)');
console.log('Range and boundary assertion tests passed');
});
it('should test empty and non-empty assertions', async () => {
console.log('Testing empty and non-empty assertions...');
// Test empty values
assertEmpty('', 'Empty string should be empty');
assertEmpty([], 'Empty array should be empty');
assertEmpty({}, 'Empty object should be empty');
// Test non-empty values
assertNotEmpty('hello', 'Non-empty string should not be empty');
assertNotEmpty([1, 2, 3], 'Non-empty array should not be empty');
assertNotEmpty({ key: 'value' }, 'Non-empty object should not be empty');
assertNotEmpty(' ', 'String with space should not be empty');
console.log('Empty and non-empty assertion tests passed');
});
it('should test error throwing assertions', async () => {
console.log('Testing error throwing assertions...');
// Test functions that should throw
assertThrows(() => {
throw new Error('This should throw');
}, 'Function should throw an error');
assertThrows(() => {
JSON.parse('invalid json');
}, 'JSON.parse with invalid input should throw');
assertThrows(() => {
const obj = null;
obj.someProperty; // This will throw TypeError
}, 'Accessing property on null should throw');
assertThrows(() => {
const func = undefined;
func(); // This will throw TypeError
}, 'Calling undefined as function should throw');
console.log('Error throwing assertion tests passed');
});
it('should test complex data validation scenarios', async () => {
console.log('Testing complex data validation scenarios...');
// Test a complete user object validation
const user = {
id: 123,
name: 'John Doe',
email: 'john.doe@example.com',
age: 30,
isActive: true,
roles: ['user', 'admin'],
profile: {
avatar: 'https://example.com/avatar.jpg',
bio: 'Software developer with 5+ years experience',
settings: {
theme: 'dark',
notifications: true
}
},
createdAt: '2024-01-15T10:30:00Z'
};
// Validate user object structure
assertExists(user, 'User object should exist');
assertTypeOf(user, 'object', 'User should be an object');
// Validate user properties
assertTypeOf(user.id, 'number', 'User ID should be a number');
assertGreaterThan(user.id, 0, 'User ID should be positive');
assertTypeOf(user.name, 'string', 'User name should be a string');
assertNotEmpty(user.name, 'User name should not be empty');
assertContainsText(user.name, 'John', 'User name should contain John');
assertMatch(user.email, /^[^@]+@[^@]+\.[^@]+$/, 'Email should be valid format');
assertTypeOf(user.age, 'number', 'User age should be a number');
assertInRange(user.age, 18, 120, 'User age should be in valid range');
assertTypeOf(user.isActive, 'boolean', 'isActive should be boolean');
assertTrue(user.isActive, 'User should be active');
// Validate array properties
assertInstanceOf(user.roles, Array, 'Roles should be an array');
assertLength(user.roles, 2, 'User should have 2 roles');
assertArrayIncludes(user.roles, 'user', 'Should include user role');
assertArrayIncludes(user.roles, 'admin', 'Should include admin role');
// Validate nested object
assertExists(user.profile, 'Profile should exist');
assertTypeOf(user.profile.bio, 'string', 'Bio should be a string');
assertContainsText(user.profile.bio, 'developer', 'Bio should mention developer');
// Validate deeply nested properties
assertExists(user.profile.settings, 'Settings should exist');
assertEqual(user.profile.settings.theme, 'dark', 'Theme should be dark');
assertTrue(user.profile.settings.notifications, 'Notifications should be enabled');
// Validate timestamp format
const isoRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
assertMatch(user.createdAt, isoRegex, 'CreatedAt should be ISO format');
console.log('Complex data validation tests passed');
});
it('should test web navigation with data URL and assertions', async () => {
console.log('Testing web navigation with assertions...');
// Create a simple HTML page with data URL to test DOM interactions
const htmlContent = [
'<html>',
' <head>',
' <title>Sample Test Page</title>',
' </head>',
' <body>',
' <h1>Welcome to Sample Test</h1>',
' <p id="message">This is a test message</p>',
' <div class="container">',
' <ul id="list">',
' <li>Item 1</li>',
' <li>Item 2</li>',
' <li>Item 3</li>',
' </ul>',
' </div>',
' <script>',
' setTimeout(() => {',
' document.getElementById("message").textContent = "Updated message";',
' }, 100);',
' </script>',
' </body>',
'</html>'
].join('\n');
const dataUrl = 'data:text/html;charset=utf-8,' + encodeURIComponent(htmlContent);
// Navigate to the test page
await navigateTo(dataUrl);
// Wait a moment for the page to load and script to execute
await new Promise(resolve => setTimeout(resolve, 200));
// Test that we can use assertions with actual web content
const currentUrl = dataUrl;
assertContainsText(currentUrl, 'data:text/html', 'URL should contain data:text/html');
assertContainsText(currentUrl, 'Sample Test Page', 'URL should contain page title');
// Test URL structure
assertTrue(currentUrl.startsWith('data:'), 'Should be a data URL');
assertGreaterThan(currentUrl.length, 100, 'URL should be substantial length');
console.log('Web navigation with assertions tests passed');
});
it('should test performance and timing assertions', async () => {
console.log('Testing performance and timing assertions...');
// Test execution time measurement
const startTime = Date.now();
// Simulate some work
await new Promise(resolve => setTimeout(resolve, 100));
const endTime = Date.now();
const executionTime = endTime - startTime;
// Validate timing
assertGreaterThanOrEqual(executionTime, 100, 'Execution time should be at least 100ms');
assertLessThan(executionTime, 200, 'Execution time should be less than 200ms');
assertInRange(executionTime, 90, 150, 'Execution time should be in expected range');
// Test timestamp validation
const timestamp = Date.now();
assertTypeOf(timestamp, 'number', 'Timestamp should be a number');
assertGreaterThan(timestamp, 1640000000000, 'Timestamp should be after 2022');
console.log('Performance and timing assertion tests passed');
});
});