upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests/integration/test-price-discovery.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration/test-price-discovery.mjs')
-rw-r--r--tests/integration/test-price-discovery.mjs138
1 files changed, 138 insertions, 0 deletions
diff --git a/tests/integration/test-price-discovery.mjs b/tests/integration/test-price-discovery.mjs
new file mode 100644
index 0000000..6762130
--- /dev/null
+++ b/tests/integration/test-price-discovery.mjs
@@ -0,0 +1,138 @@
1import { execSync } from 'child_process';
2
3const BOARD_A_IP = process.env.TOLLGATE_IP || '10.185.47.1';
4const BOARD_B_IP = process.env.TOLLGATE_B_IP || process.env.TOLLGATE_IP_B || '10.192.45.1';
5const API_A = `http://${BOARD_A_IP}:2121`;
6const API_B = `http://${BOARD_B_IP}:2121`;
7
8function run(cmd) {
9 try { return execSync(cmd, { encoding: 'utf8', timeout: 15000 }); }
10 catch (e) { return e.stdout || null; }
11}
12
13function runJson(cmd) {
14 const out = run(cmd);
15 try { return out ? JSON.parse(out) : null; }
16 catch { return null; }
17}
18
19let passed = 0, failed = 0;
20function assert(cond, msg) {
21 if (cond) { console.log(` PASS: ${msg}`); passed++; }
22 else { console.log(` FAIL: ${msg}`); failed++; }
23}
24
25function canReach(url) {
26 const result = run(`curl -s --connect-timeout 3 --max-time 5 -o /dev/null -w "%{http_code}" ${url}`);
27 return result && result.trim() !== '000' && result.trim() !== '';
28}
29
30console.log('=== test-price-discovery (two-board) ===\n');
31
32const reachA = canReach(`${API_A}/market`);
33const reachB = canReach(`${API_B}/market`);
34
35console.log(`Reachability: Board A=${reachA ? 'YES' : 'NO'}, Board B=${reachB ? 'YES' : 'NO'}\n`);
36
37if (!reachA && !reachB) {
38 console.log('FATAL: Neither board reachable. Check TOLLGATE_IP and TOLLGATE_B_IP');
39 process.exit(1);
40}
41
42console.log('--- Board A: market endpoint ---');
43{
44 if (reachA) {
45 const data = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
46 assert(data !== null, 'Board A /market returns JSON');
47 assert(typeof data?.count === 'number', `Board A count is ${data?.count}`);
48 if (data && data.entries) {
49 console.log(` Board A sees ${data.count} nearby TollGate(s):`);
50 for (const e of data.entries) {
51 console.log(` ${e.ssid} (BSSID: ${e.bssid}) — ${e.price_per_step} sats/step, RSSI: ${e.rssi}`);
52 }
53 }
54 } else {
55 console.log(' SKIP: Board A not reachable');
56 }
57}
58
59console.log('\n--- Board B: market endpoint ---');
60{
61 if (reachB) {
62 const data = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
63 assert(data !== null, 'Board B /market returns JSON');
64 assert(typeof data?.count === 'number', `Board B count is ${data?.count}`);
65 if (data && data.entries) {
66 console.log(` Board B sees ${data.count} nearby TollGate(s):`);
67 for (const e of data.entries) {
68 console.log(` ${e.ssid} (BSSID: ${e.bssid}) — ${e.price_per_step} sats/step, RSSI: ${e.rssi}`);
69 }
70 }
71 } else {
72 console.log(' SKIP: Board B not reachable');
73 }
74}
75
76console.log('\n--- Cross-discovery: Board A sees Board B ---');
77{
78 if (reachA) {
79 const mktA = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
80 if (mktA && mktA.count > 0) {
81 const foundB = mktA.entries.some(e =>
82 e.ssid.startsWith('TollGate-') && e.bssid !== '' && e.price_per_step > 0
83 );
84 assert(foundB, `Board A discovered another TollGate (count=${mktA.count})`);
85 } else {
86 console.log(' INFO: Board A has 0 entries. Scan may need more time.');
87 }
88 } else {
89 console.log(' SKIP: Board A not reachable');
90 }
91}
92
93console.log('\n--- Cross-discovery: Board B sees Board A ---');
94{
95 if (reachB) {
96 const mktB = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
97 if (mktB && mktB.count > 0) {
98 const foundA = mktB.entries.some(e =>
99 e.ssid.startsWith('TollGate-') && e.bssid !== '' && e.price_per_step > 0
100 );
101 assert(foundA, `Board B discovered another TollGate (count=${mktB.count})`);
102 } else {
103 console.log(' INFO: Board B has 0 entries. Scan may need more time.');
104 }
105 } else {
106 console.log(' SKIP: Board B not reachable');
107 }
108}
109
110console.log('\n--- Discovery data integrity ---');
111{
112 const boards = [];
113 if (reachA) {
114 const mktA = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_A}/market`);
115 if (mktA?.entries) boards.push({ name: 'A', data: mktA });
116 }
117 if (reachB) {
118 const mktB = runJson(`curl -s --connect-timeout 5 --max-time 10 ${API_B}/market`);
119 if (mktB?.entries) boards.push({ name: 'B', data: mktB });
120 }
121
122 for (const { name, data } of boards) {
123 for (const e of data.entries) {
124 assert(typeof e.price_per_step === 'number' && e.price_per_step > 0,
125 `Board ${name} entry has valid price (${e.price_per_step})`);
126 assert(typeof e.step_size === 'number' && e.step_size > 0,
127 `Board ${name} entry has valid step_size (${e.step_size})`);
128 assert(typeof e.metric === 'string' && e.metric.length > 0,
129 `Board ${name} entry has valid metric (${e.metric})`);
130 assert(typeof e.rssi === 'number',
131 `Board ${name} entry has valid RSSI (${e.rssi})`);
132 break;
133 }
134 }
135}
136
137console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`);
138process.exit(failed > 0 ? 1 : 0);