#!/usr/bin/env node
const { spawn } = require('child_process');
const readline = require('readline');
const path = require('path');
const TEST_CASE = {
name: 'Saola March to July 2025',
credentials: {
username: 'david+saola@umbrellacost.com',
password: process.env.SAOLA_PASSWORD
},
requests: [
{
id: 1,
method: 'tools/call',
params: {
name: 'authenticate_user',
arguments: {
username: 'david+saola@umbrellacost.com',
password: process.env.SAOLA_PASSWORD
}
}
},
{
id: 2,
method: 'tools/call',
params: {
name: 'api___invoices_caui',
arguments: {
startDate: '2025-03-01',
endDate: '2025-07-31',
periodGranLevel: 'month',
groupBy: 'none',
costType: '["cost", "discount"]',
isUnblended: 'true'
}
}
}
],
expected: {
// Values from MANUAL_ANSWERS.txt - 4 decimal places
monthlyTotals: {
'2025-03': 104755.0743,
'2025-04': 111340.4244,
'2025-05': 149774.2380,
'2025-06': 165666.5701,
'2025-07': 183920.5781
},
accountId: '932213950603'
}
};
function sendRequest(proc, request) {
const jsonRequest = JSON.stringify({
jsonrpc: '2.0',
...request
});
proc.stdin.write(jsonRequest + '\n');
}
function parseResponse(line) {
try {
if (line.trim().startsWith('{') && line.includes('jsonrpc')) {
return JSON.parse(line);
}
} catch (e) {}
return null;
}
async function runTest() {
return new Promise((resolve) => {
console.log('Testing: Saola Account (March-July 2025)');
const result = {
passed: false,
errors: []
};
const proc = spawn('node', [path.join(__dirname, '../dist/index.js')], {
env: process.env
});
const rl = readline.createInterface({
input: proc.stdout,
crlfDelay: Infinity
});
rl.on('line', (line) => {
if (!result.passed && line.includes('"serverInfo"')) {
sendRequest(proc, TEST_CASE.requests[0]);
}
const response = parseResponse(line);
if (response && response.id) {
if (response.id === 1) {
if (response.result) {
sendRequest(proc, TEST_CASE.requests[1]);
} else if (response.error) {
console.log(` ❌ Authentication failed: ${response.error.message}`);
result.errors.push(`Authentication failed: ${response.error.message}`);
proc.kill();
resolve(result);
}
} else if (response.id === 2) {
if (response.result) {
let data = null;
if (response.result.content && response.result.content[0] && response.result.content[0].text) {
const content = response.result.content[0].text;
const jsonMatch = content.match(/```json\n([\s\S]*?)\n```/);
if (jsonMatch) {
data = JSON.parse(jsonMatch[1]);
}
}
if (data && Array.isArray(data)) {
let allPassed = true;
const actualByMonth = {};
data.forEach(row => {
actualByMonth[row.usage_date] = row.total_cost;
});
for (const [month, expectedCost] of Object.entries(TEST_CASE.expected.monthlyTotals)) {
const actualCost = actualByMonth[month];
// Round both to 4 decimal places for comparison
const roundedActual = actualCost ? Math.round(actualCost * 10000) / 10000 : undefined;
const roundedExpected = Math.round(expectedCost * 10000) / 10000;
if (actualCost === undefined) {
console.log(` ❌ ${month}: Missing data`);
result.errors.push(`${month}: Missing data`);
allPassed = false;
} else if (roundedActual !== roundedExpected) {
console.log(` ❌ ${month}: Expected ${expectedCost}, got ${actualCost}`);
result.errors.push(`${month}: Mismatch`);
allPassed = false;
} else {
console.log(` ✅ ${month}: ${roundedActual} (matches to 4 decimal places)`);
}
}
if (data[0] && data[0].account_id !== TEST_CASE.expected.accountId) {
console.log(` ❌ Account ID: Expected ${TEST_CASE.expected.accountId}, got ${data[0].account_id}`);
result.errors.push('Wrong account ID');
allPassed = false;
} else if (data[0]) {
console.log(` ✅ Account ID: ${data[0].account_id}`);
}
result.passed = allPassed;
} else {
result.errors.push('No data in response');
}
} else if (response.error) {
result.errors.push(`API call failed: ${response.error.message}`);
}
proc.kill();
resolve(result);
}
}
});
proc.stderr.on('data', () => {});
sendRequest(proc, {
jsonrpc: '2.0',
method: 'initialize',
params: {
protocolVersion: '1.0.0',
capabilities: {},
clientInfo: { name: 'test-client', version: '1.0.0' }
},
id: 0
});
setTimeout(() => {
if (!result.passed && result.errors.length === 0) {
result.errors.push('Test timeout');
proc.kill();
resolve(result);
}
}, 30000);
});
}
runTest().then((result) => {
if (result.passed) {
console.log('\n✅ Saola test PASSED - Exact match!');
process.exit(0);
} else {
console.log('\n❌ Saola test FAILED');
process.exit(1);
}
});