307 lines
8.6 KiB
JavaScript
307 lines
8.6 KiB
JavaScript
/**
|
|
* Frontend Integration Test
|
|
* Tests all form types, navigation, validation, and summary functionality
|
|
*/
|
|
|
|
import { JSDOM } from 'jsdom';
|
|
import { readFileSync } from 'fs';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// Load the HTML file
|
|
const htmlPath = join(__dirname, '../public/index.html');
|
|
const html = readFileSync(htmlPath, 'utf-8');
|
|
|
|
// Mock questions data covering all form types
|
|
const mockQuestions = [
|
|
{
|
|
key: 'email',
|
|
label: 'E-Mail Adresse',
|
|
type: 'email',
|
|
required: true,
|
|
step: 1,
|
|
order: 1,
|
|
helpText: 'Ihre E-Mail für Benachrichtigungen'
|
|
},
|
|
{
|
|
key: 'name',
|
|
label: 'Name',
|
|
type: 'text',
|
|
required: true,
|
|
step: 1,
|
|
order: 2
|
|
},
|
|
{
|
|
key: 'priority',
|
|
label: 'Priorität',
|
|
type: 'select',
|
|
required: true,
|
|
step: 2,
|
|
order: 1,
|
|
optionsJson: JSON.stringify(['Hoch', 'Mittel', 'Niedrig'])
|
|
},
|
|
{
|
|
key: 'categories',
|
|
label: 'Kategorien',
|
|
type: 'multiselect',
|
|
required: false,
|
|
step: 2,
|
|
order: 2,
|
|
optionsJson: JSON.stringify(['Arbeit', 'Privat', 'Newsletter', 'Spam'])
|
|
},
|
|
{
|
|
key: 'description',
|
|
label: 'Beschreibung',
|
|
type: 'textarea',
|
|
required: false,
|
|
step: 3,
|
|
order: 1,
|
|
helpText: 'Zusätzliche Informationen'
|
|
}
|
|
];
|
|
|
|
console.log('🧪 Starting Frontend Integration Tests...\n');
|
|
|
|
// Test 1: Verify all form types render correctly
|
|
function testFormTypeRendering() {
|
|
console.log('Test 1: Form Type Rendering');
|
|
|
|
const dom = new JSDOM(html, { runScripts: 'dangerously', resources: 'usable' });
|
|
const { window } = dom;
|
|
const { document } = window;
|
|
|
|
// Mock fetch for questions
|
|
window.fetch = async (url) => {
|
|
if (url.includes('/api/questions')) {
|
|
return {
|
|
json: async () => mockQuestions
|
|
};
|
|
}
|
|
};
|
|
|
|
// Wait for questions to load
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
const container = document.getElementById('form-container');
|
|
|
|
// Check text input
|
|
const textInput = document.querySelector('input[type="text"]');
|
|
console.log(' ✓ Text input rendered:', textInput !== null);
|
|
|
|
// Check email input
|
|
const emailInput = document.querySelector('input[type="email"]');
|
|
console.log(' ✓ Email input rendered:', emailInput !== null);
|
|
|
|
// Check required markers
|
|
const labels = Array.from(document.querySelectorAll('label'));
|
|
const hasRequiredMarker = labels.some(l => l.textContent.includes('*'));
|
|
console.log(' ✓ Required field markers present:', hasRequiredMarker);
|
|
|
|
// Check help text
|
|
const helpText = document.querySelector('small');
|
|
console.log(' ✓ Help text rendered:', helpText !== null);
|
|
|
|
window.close();
|
|
resolve();
|
|
}, 100);
|
|
});
|
|
}
|
|
|
|
// Test 2: Verify navigation between steps
|
|
function testStepNavigation() {
|
|
console.log('\nTest 2: Step Navigation');
|
|
|
|
const dom = new JSDOM(html, { runScripts: 'dangerously' });
|
|
const { window } = dom;
|
|
const { document } = window;
|
|
|
|
window.fetch = async (url) => {
|
|
if (url.includes('/api/questions')) {
|
|
return { json: async () => mockQuestions };
|
|
}
|
|
};
|
|
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
const prevBtn = document.getElementById('prev-btn');
|
|
const nextBtn = document.getElementById('next-btn');
|
|
|
|
// Check initial state (step 1)
|
|
console.log(' ✓ Previous button hidden on step 1:', prevBtn.style.display === 'none');
|
|
console.log(' ✓ Next button visible:', nextBtn.style.display !== 'none');
|
|
|
|
// Simulate filling required fields
|
|
const emailInput = document.querySelector('input[type="email"]');
|
|
const textInput = document.querySelector('input[type="text"]');
|
|
if (emailInput) emailInput.value = 'test@example.com';
|
|
if (textInput) textInput.value = 'Test User';
|
|
|
|
// Click next
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
console.log(' ✓ Previous button visible on step 2:', prevBtn.style.display !== 'none');
|
|
|
|
window.close();
|
|
resolve();
|
|
}, 50);
|
|
}, 100);
|
|
});
|
|
}
|
|
|
|
// Test 3: Verify validation of required fields
|
|
function testRequiredFieldValidation() {
|
|
console.log('\nTest 3: Required Field Validation');
|
|
|
|
const dom = new JSDOM(html, { runScripts: 'dangerously' });
|
|
const { window } = dom;
|
|
const { document } = window;
|
|
|
|
// Mock alert
|
|
let alertCalled = false;
|
|
window.alert = (msg) => {
|
|
alertCalled = true;
|
|
console.log(' ✓ Validation alert triggered:', msg);
|
|
};
|
|
|
|
window.fetch = async (url) => {
|
|
if (url.includes('/api/questions')) {
|
|
return { json: async () => mockQuestions };
|
|
}
|
|
};
|
|
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
const nextBtn = document.getElementById('next-btn');
|
|
|
|
// Try to proceed without filling required fields
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
console.log(' ✓ Validation prevents navigation:', alertCalled);
|
|
|
|
window.close();
|
|
resolve();
|
|
}, 50);
|
|
}, 100);
|
|
});
|
|
}
|
|
|
|
// Test 4: Verify summary and buy button
|
|
function testSummaryAndBuyButton() {
|
|
console.log('\nTest 4: Summary and Buy Button');
|
|
|
|
const dom = new JSDOM(html, { runScripts: 'dangerously' });
|
|
const { window } = dom;
|
|
const { document } = window;
|
|
|
|
window.fetch = async (url) => {
|
|
if (url.includes('/api/questions')) {
|
|
return { json: async () => mockQuestions };
|
|
}
|
|
};
|
|
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
// Fill all required fields and navigate to summary
|
|
const emailInput = document.querySelector('input[type="email"]');
|
|
const textInput = document.querySelector('input[type="text"]');
|
|
|
|
if (emailInput) emailInput.value = 'test@example.com';
|
|
if (textInput) textInput.value = 'Test User';
|
|
|
|
// Navigate through all steps
|
|
const nextBtn = document.getElementById('next-btn');
|
|
|
|
// Step 1 -> 2
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
const selectInput = document.querySelector('select:not([multiple])');
|
|
if (selectInput) selectInput.value = 'Hoch';
|
|
|
|
// Step 2 -> 3
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
// Step 3 -> Summary
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
const summary = document.getElementById('summary');
|
|
const buyBtn = document.getElementById('buy-btn');
|
|
const summaryContent = document.getElementById('summary-content');
|
|
|
|
console.log(' ✓ Summary section visible:', summary.style.display !== 'none');
|
|
console.log(' ✓ Buy button present:', buyBtn !== null);
|
|
console.log(' ✓ Summary content populated:', summaryContent.children.length > 0);
|
|
|
|
window.close();
|
|
resolve();
|
|
}, 50);
|
|
}, 50);
|
|
}, 50);
|
|
}, 100);
|
|
});
|
|
}
|
|
|
|
// Test 5: Verify multiselect handling
|
|
function testMultiselectHandling() {
|
|
console.log('\nTest 5: Multiselect Handling');
|
|
|
|
const dom = new JSDOM(html, { runScripts: 'dangerously' });
|
|
const { window } = dom;
|
|
const { document } = window;
|
|
|
|
window.fetch = async (url) => {
|
|
if (url.includes('/api/questions')) {
|
|
return { json: async () => mockQuestions };
|
|
}
|
|
};
|
|
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
// Navigate to step 2 where multiselect is
|
|
const emailInput = document.querySelector('input[type="email"]');
|
|
const textInput = document.querySelector('input[type="text"]');
|
|
|
|
if (emailInput) emailInput.value = 'test@example.com';
|
|
if (textInput) textInput.value = 'Test User';
|
|
|
|
const nextBtn = document.getElementById('next-btn');
|
|
nextBtn.click();
|
|
|
|
setTimeout(() => {
|
|
const multiselect = document.querySelector('select[multiple]');
|
|
console.log(' ✓ Multiselect rendered:', multiselect !== null);
|
|
console.log(' ✓ Multiselect has size attribute:', multiselect?.size === 5);
|
|
console.log(' ✓ Multiselect has options:', multiselect?.options.length > 0);
|
|
|
|
window.close();
|
|
resolve();
|
|
}, 50);
|
|
}, 100);
|
|
});
|
|
}
|
|
|
|
// Run all tests
|
|
async function runTests() {
|
|
try {
|
|
await testFormTypeRendering();
|
|
await testStepNavigation();
|
|
await testRequiredFieldValidation();
|
|
await testSummaryAndBuyButton();
|
|
await testMultiselectHandling();
|
|
|
|
console.log('\n✅ All frontend integration tests completed!\n');
|
|
} catch (error) {
|
|
console.error('\n❌ Test failed:', error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
runTests();
|