weekly-repricing-cli.test.js
1 /** 2 * CLI subprocess tests for src/cron/weekly-repricing.js 3 * Tests the CLI block (lines 437-445) and main() (lines 381-435) 4 * by running weekly-repricing.js as a subprocess. 5 * c8 collects coverage from subprocesses via NODE_V8_COVERAGE env var inheritance. 6 */ 7 8 import { test, describe } from 'node:test'; 9 import assert from 'node:assert/strict'; 10 import { execSync } from 'child_process'; 11 import { join, dirname } from 'path'; 12 import { fileURLToPath } from 'url'; 13 import Database from 'better-sqlite3'; 14 15 const __dirname = dirname(fileURLToPath(import.meta.url)); 16 const repricingFile = join(__dirname, '../..', 'src', 'cron', 'weekly-repricing.js'); 17 18 /** 19 * Create a minimal test database for repricing CLI tests 20 */ 21 function createCliTestDb() { 22 const dbPath = `/tmp/weekly-repricing-cli-test-${Date.now()}.db`; 23 const db = new Database(dbPath); 24 25 db.exec(` 26 CREATE TABLE countries ( 27 id INTEGER PRIMARY KEY, 28 country_code TEXT UNIQUE NOT NULL, 29 currency_code TEXT NOT NULL, 30 pricing_tier TEXT DEFAULT 'standard', 31 ppp_index REAL DEFAULT 1.0, 32 price_local INTEGER DEFAULT 29700, 33 is_active INTEGER DEFAULT 1, 34 updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, 35 twilio_phone_number TEXT 36 ); 37 `); 38 39 // Insert a few test countries 40 db.prepare( 41 'INSERT INTO countries (country_code, currency_code, pricing_tier, ppp_index, price_local) VALUES (?, ?, ?, ?, ?)' 42 ).run('AU', 'AUD', 'standard', 0.85, 44700); 43 44 db.prepare( 45 'INSERT INTO countries (country_code, currency_code, pricing_tier, ppp_index, price_local) VALUES (?, ?, ?, ?, ?)' 46 ).run('US', 'USD', 'standard', 1.0, 29700); 47 48 db.close(); 49 return dbPath; 50 } 51 52 function runCli(dbPath, extraEnv = {}) { 53 try { 54 const result = execSync(`node ${repricingFile}`, { 55 env: { 56 ...process.env, 57 DATABASE_PATH: dbPath, 58 NODE_ENV: 'test', 59 // No FIXER_API_KEY — main() will fail at fetchExchangeRates, return 1 60 ...extraEnv, 61 }, 62 encoding: 'utf8', 63 timeout: 15000, 64 }); 65 return { stdout: result, exitCode: 0 }; 66 } catch (err) { 67 return { stdout: err.stdout || '', stderr: err.stderr || '', exitCode: err.status || 1 }; 68 } 69 } 70 71 describe('weekly-repricing.js CLI', () => { 72 test('runs main() and exits 1 when FIXER_API_KEY is not set', () => { 73 const dbPath = createCliTestDb(); 74 // Without FIXER_API_KEY, fetchExchangeRates throws, main() catches and returns 1 75 const result = runCli(dbPath, { FIXER_API_KEY: '' }); 76 // Should exit with code 1 (main returns 1 on error) 77 assert.equal(result.exitCode, 1); 78 }); 79 80 test('CLI block is reached and exits via main().then(process.exit)', () => { 81 const dbPath = createCliTestDb(); 82 const result = runCli(dbPath); 83 // exits 0 or 1 depending on success - either way, main() was called 84 assert.ok(result.exitCode === 0 || result.exitCode === 1); 85 }); 86 });