[object Object]

← back to Costa Rica

costa-rica: marketplace test suite (money conservation, JWT, scrypt, sandbox) 7/7 green — TK-10346 yoloforever c1

8c31834f6b43c9bdd5815669bb3f7e263a7e41ce · 2026-08-07 10:04:51 -0700 · Steve

Files touched

Diff

commit 8c31834f6b43c9bdd5815669bb3f7e263a7e41ce
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Aug 7 10:04:51 2026 -0700

    costa-rica: marketplace test suite (money conservation, JWT, scrypt, sandbox) 7/7 green — TK-10346 yoloforever c1
---
 package.json             |  3 ++-
 test/marketplace.test.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 91d413a..e860890 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
   "scripts": {
     "start": "node server.js",
     "schema": "psql costa_rica_directory -f schema.sql",
-    "seed": "psql costa_rica_directory -f scripts/seed.sql"
+    "seed": "psql costa_rica_directory -f scripts/seed.sql",
+    "test": "node --test test/*.test.js"
   },
   "dependencies": {
     "dotenv": "^16.4.5",
diff --git a/test/marketplace.test.js b/test/marketplace.test.js
new file mode 100644
index 0000000..e42f514
--- /dev/null
+++ b/test/marketplace.test.js
@@ -0,0 +1,52 @@
+'use strict';
+// Zero-dependency tests (node:test) for the marketplace money + auth core.
+// Run: node --test
+const { test } = require('node:test');
+const assert = require('node:assert');
+const { computeSplit, nights } = require('../lib/money');
+const { signToken, verifyToken, hashPassword, verifyPassword } = require('../lib/auth');
+
+test('nights counts calendar nights', () => {
+  assert.equal(nights('2026-09-10', '2026-09-13'), 3);
+  assert.equal(nights('2026-09-10', '2026-09-10'), 0);
+});
+
+test('computeSplit: 3 nights @ $120 + $40 cleaning, 10% fee', () => {
+  const s = computeSplit({ subtotal: 12000 * 3, cleaningFee: 4000, currency: 'USD', platformFeeBps: 1000 });
+  assert.equal(s.total, 40000);        // 360 + 40 cleaning = 400.00
+  assert.equal(s.platformFee, 4000);   // 10% of 400
+  assert.equal(s.hostPayout, 36000);   // total - platformFee
+  assert.equal(s.hostPayout + s.platformFee, s.total); // conservation: no cents lost
+});
+
+test('computeSplit: host + platform always reconstruct total (no rounding drift)', () => {
+  for (const [sub, clean, bps] of [[3333, 777, 1000], [9999, 0, 1250], [10001, 501, 999]]) {
+    const s = computeSplit({ subtotal: sub, cleaningFee: clean, currency: 'CRC', platformFeeBps: bps });
+    assert.equal(s.hostPayout + s.platformFee + s.processorFee, s.total);
+  }
+});
+
+test('JWT round-trips and rejects tampering', () => {
+  const t = signToken({ sub: 42, role: 'traveler' });
+  const claims = verifyToken(t);
+  assert.equal(claims.sub, 42);
+  assert.equal(verifyToken(t.slice(0, -3) + 'xxx'), null);   // bad signature
+  assert.equal(verifyToken('not.a.jwt'), null);
+});
+
+test('JWT honors expiry', () => {
+  const expired = signToken({ sub: 1 }, -10); // already expired
+  assert.equal(verifyToken(expired), null);
+});
+
+test('scrypt password hash verifies and rejects wrong password', () => {
+  const h = hashPassword('correct horse');
+  assert.ok(verifyPassword('correct horse', h));
+  assert.ok(!verifyPassword('wrong horse', h));
+  assert.ok(!verifyPassword('correct horse', 'garbage'));
+});
+
+test('payment provider is sandbox by default (no live creds)', () => {
+  const { getProvider } = require('../lib/payments');
+  assert.equal(getProvider().liveMode, false);
+});

← d34e822 costa-rica: document marketplace env surface in .env.example  ·  back to Costa Rica  ·  costa-rica: Cody gate fixes (c1) — JWT_SECRET isolation+prod b133da0 →