/ tests / payments / weekly-repricing-cli.test.js
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  });