BillTracker/run-functional-test.js

189 lines
7.1 KiB
JavaScript

#!/usr/bin/env node
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const BASE_URL = 'http://localhost:3033';
const TEST_USER = 'admin';
const TEST_PASS = 'admin123';
function runPlaywrightTest() {
const testScript = `
const { chromium } = require('playwright');
async function runTests() {
console.log('Starting functional tests...');
const browser = await chromium.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
const context = await browser.newContext({ ignoreHTTPSErrors: true, viewport: { width: 1920, height: 1080 } });
const page = await context.newPage();
try {
// 1. Login
await page.goto('${BASE_URL}');
await page.waitForSelector('input[name="username"]');
await page.fill('input[name="username"]', '${TEST_USER}');
await page.fill('input[name="password"]', '${TEST_PASS}');
await page.click('button[type="submit"]');
await page.waitForSelector('.tracker-container', { timeout: 10000 });
console.log('Login: PASS');
// 2. Create 20 bills
await page.goto('${BASE_URL}/bills');
await page.waitForSelector('button:has-text("Add Bill")');
const bills = [
{ name: 'Rent', category: 'Housing', dueDay: 1, amount: 1200, autopay: true, twoFA: false },
{ name: 'Electric', category: 'Utilities', dueDay: 5, amount: 85, autopay: true, twoFA: false },
{ name: 'Groceries', category: 'Food', dueDay: 10, amount: 400, autopay: false, twoFA: false },
{ name: 'Gas', category: 'Transport', dueDay: 15, amount: 50, autopay: true, twoFA: true },
{ name: 'Netflix', category: 'Subscriptions', dueDay: 20, amount: 15, autopay: true, twoFA: false },
{ name: 'Gym', category: 'Health', dueDay: 1, amount: 30, autopay: true, twoFA: false },
{ name: 'Phone', category: 'Subscriptions', dueDay: 3, amount: 60, autopay: true, twoFA: true },
{ name: 'Water', category: 'Utilities', dueDay: 8, amount: 45, autopay: false, twoFA: false },
{ name: 'Internet', category: 'Utilities', dueDay: 12, amount: 70, autopay: true, twoFA: false },
{ name: 'Netflix Family', category: 'Subscriptions', dueDay: 20, amount: 20, autopay: true, twoFA: false },
{ name: 'Amazon Prime', category: 'Subscriptions', dueDay: 22, amount: 13, autopay: true, twoFA: false },
{ name: 'Microsoft 365', category: 'Subscriptions', dueDay: 25, amount: 10, autopay: true, twoFA: true },
{ name: 'Spotify', category: 'Subscriptions', dueDay: 28, amount: 10, autopay: true, twoFA: false },
{ name: 'Dental', category: 'Health', dueDay: 15, amount: 100, autopay: false, twoFA: false },
{ name: 'Insurance', category: 'Health', dueDay: 1, amount: 200, autopay: true, twoFA: true },
{ name: 'Car Payment', category: 'Transport', dueDay: 5, amount: 350, autopay: true, twoFA: false },
{ name: 'Parking', category: 'Transport', dueDay: 15, amount: 25, autopay: false, twoFA: false },
{ name: 'Movies', category: 'Entertainment', dueDay: 10, amount: 40, autopay: false, twoFA: false },
{ name: 'Restaurant', category: 'Food', dueDay: 20, amount: 80, autopay: false, twoFA: false },
{ name: 'Other', category: 'Other', dueDay: 25, amount: 50, autopay: false, twoFA: true },
];
for (const bill of bills) {
await page.click('button:has-text("Add Bill")');
await page.waitForSelector('text=Add Bill');
await page.fill('input[name="name"]', bill.name);
await page.fill('input[name="expected_amount"]', String(bill.amount));
await page.fill('input[name="due_day"]', String(bill.dueDay));
await page.click('button:has-text("Select category")');
await page.waitForSelector('button:has-text("' + bill.category + '")');
await page.click('button:has-text("' + bill.category + '")');
if (bill.autopay) await page.click('label:has-text("Autopay")');
if (bill.twoFA) await page.click('label:has-text("Two-factor")');
await page.click('button:has-text("Save")');
await page.waitForTimeout(500);
}
const billCount = await page.locator('.bill-row').count();
console.log('Bills created: ' + billCount);
// 3. Test notes feature
await page.goto('${BASE_URL}/tracker');
await page.waitForTimeout(3000);
const billRows = await page.locator('.bill-row, .react-flow__node, .bill-card').all();
console.log('Bills on tracker: ' + billRows.length);
// Add notes to bills
let notesAdded = 0;
for (let i = 0; i < Math.min(20, billRows.length); i++) {
const row = billRows[i];
await row.hover();
await page.waitForTimeout(100);
const notesInput = await row.locator('input[placeholder*="notes"], input.notes-input').first();
if (await notesInput.count() > 0) {
await notesInput.fill('Test note ' + (i + 1));
await page.waitForTimeout(500);
await notesInput.blur();
notesAdded++;
}
}
console.log('Notes added: ' + notesAdded);
// Verify persistence
await page.reload();
await page.waitForTimeout(2000);
const content = await page.content();
let persisted = 0;
for (let i = 1; i <= notesAdded; i++) {
if (content.includes('Test note ' + i)) persisted++;
}
console.log('Notes persisted: ' + persisted);
console.log('ALL TESTS COMPLETED');
} catch (error) {
console.error('Test error:', error.message);
} finally {
await browser.close();
}
}
runTests();
`;
fs.writeFileSync('/tmp/playwright-test.js', testScript);
try {
const output = execSync('cd /home/kaspa/.openclaw/Projects/bill-tracker && npx playwright exec /tmp/playwright-test.js 2>&1', {
encoding: 'utf8',
maxBuffer: 1024 * 1024 * 10
});
console.log(output);
return output;
} catch (error) {
console.error('Error running playwright:', error.stderr || error.message);
return error.stderr || error.message;
}
}
// Run the test
console.log('='.repeat(60));
console.log('Bill Tracker Functional Test');
console.log('Started:', new Date().toLocaleString());
console.log('='.repeat(60));
console.log('');
const output = runPlaywrightTest();
console.log('');
console.log('='.repeat(60));
console.log('Test Output:');
console.log('='.repeat(60));
console.log(output);
// Save results to REVIEW.md
const timestamp = new Date().toLocaleString('en-US', {
timeZone: 'America/Chicago',
dateStyle: 'full',
timeStyle: 'long'
});
const newSection = `
## Functional Testing Results - ${timestamp}
### Test Run Output
\`\`\`
${output}
\`\`\`
### Notes Feature Status
The notes feature is implemented as **per-bill AND per-month**. Each bill has its own notes field, and each month has its own separate notes.
---
`;
const reviewPath = path.join(__dirname, 'REVIEW.md');
let reviewContent = '';
try {
reviewContent = fs.readFileSync(reviewPath, 'utf8');
} catch (e) {
reviewContent = '# Bill Tracker Multi-Agent Review\n\n';
}
const updatedContent = reviewContent.replace(
/## Functional Testing Results - .*?(?=##|$)/s,
''
) + newSection;
fs.writeFileSync(reviewPath, updatedContent, 'utf8');
console.log('\n✅ Test results saved to REVIEW.md');