const path = require('path');
const { startRelay } = require('./helpers/relay');
const { setupPanic, teardownPanic } = require('./helpers/setup');
const binPath = path.resolve(__dirname, '../../target/debug/beam');
const config = {
panicPort: 8765,
relayPort: 9100,
runId: Date.now().toString(36),
};
const { clients, alice, bob } = setupPanic({ numClients: 2, panicPort: config.panicPort });
const BOOT = 'if (!globalThis.user) { await require("./helpers/gunboot").bootGun(test.props.relayPort); }';
describe('16. SEA User Accounts: create/auth/save/subscribe against BEAM (headless)', function () {
this.timeout(300000);
it('Two clients connected to panic-server', function () {
return clients.atLeast(2);
});
it('BEAM relay started', function () {
this.timeout(10000);
startRelay({ binPath, port: config.relayPort });
return new Promise((resolve) => setTimeout(resolve, 2000));
});
it('Create Alice', function () {
return alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
const alias = 'panicAlice' + test.props.runId;
user.create(alias, 'xyzabcmnopq', function (ack) {
if (ack.err || !ack.pub) { test.fail('create failed: ' + (ack.err || 'no pub')); return; }
globalThis.alicePub = ack.pub;
test.done();
});
setTimeout(() => test.fail('timeout — create Alice in 60s'), 60000);
}, { runId: config.runId, relayPort: config.relayPort });
});
it('Create Bob', function () {
return bob.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
const alias = 'panicBob' + test.props.runId;
user.create(alias, 'zyxcbaqponm', function (ack) {
if (ack.err || !ack.pub) { test.fail('create failed: ' + (ack.err || 'no pub')); return; }
globalThis.bobPub = ack.pub;
test.done();
});
setTimeout(() => test.fail('timeout — create Bob in 60s'), 60000);
}, { runId: config.runId, relayPort: config.relayPort });
});
it('Auth Alice', function () {
return alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
const alias = 'panicAlice' + test.props.runId;
user.auth(alias, 'xyzabcmnopq', function (ack) {
if (ack.err || !ack.pub) { test.fail('auth failed: ' + (ack.err || 'no pub')); return; }
test.done();
});
setTimeout(() => test.fail('timeout — auth Alice in 60s'), 60000);
}, { runId: config.runId, relayPort: config.relayPort });
});
it('Auth Bob', function () {
return bob.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
const alias = 'panicBob' + test.props.runId;
user.auth(alias, 'zyxcbaqponm', function (ack) {
if (ack.err || !ack.pub) { test.fail('auth failed: ' + (ack.err || 'no pub')); return; }
test.done();
});
setTimeout(() => test.fail('timeout — auth Bob in 60s'), 60000);
}, { runId: config.runId, relayPort: config.relayPort });
});
it('Alice: self-subscribe + user-space put (hello=world lands via BEAM)', function () {
return alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
user.on(function (aliceData) {
if (aliceData && aliceData.hello === 'world') {
test.done();
}
});
setTimeout(function () {
user.get('hello').put('world');
}, 500);
setTimeout(() => test.fail('timeout — self put/subscribe in 30s'), 30000);
}, { relayPort: config.relayPort });
});
it('Alice subscribes to Bob via alias discovery; Bob puts mars', function () {
const aliceP = alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
gun.get('alias/panicBob' + test.props.runId).map().on(function (data) {
if (data && data.pub) {
globalThis.discoveredBobPub = data.pub;
}
});
gun.get('pub/' + globalThis.bobPub).get('hello').on(function (value) {
if (value === 'mars') {
test.done();
}
});
setTimeout(() => test.fail('timeout — never saw Bob mars in 45s'), 45000);
}, { runId: config.runId, relayPort: config.relayPort });
return aliceP.then(() => {
return bob.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
user.on(function (bobData) {
if (bobData && bobData.hello === 'mars') {
test.done();
}
});
setTimeout(function () {
user.get('hello').put('mars');
}, 500);
setTimeout(() => test.fail('timeout — bob put/subscribe in 30s'), 30000);
}, { relayPort: config.relayPort });
});
});
it('Alice received Bob mars through BEAM', function () {
return alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
const start = Date.now();
const check = setInterval(() => {
if (globalThis.discoveredBobPub === globalThis.bobPub) {
clearInterval(check);
test.done();
} else if (Date.now() - start > 20000) {
clearInterval(check);
test.fail('alias discovery incomplete: discovered=' + globalThis.discoveredBobPub);
}
}, 200);
}, { relayPort: config.relayPort });
});
it('Alice tries to crack Bob; Bob space stays intact', function () {
const crackP = alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
gun.get('pub/' + globalThis.bobPub).get('crackers').put('gonna crack');
setTimeout(() => test.done(), 1500);
}, { relayPort: config.relayPort });
return crackP.then(() => {
return alice.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
gun.get('pub/' + globalThis.bobPub).val(function (data) {
if (data.pub === globalThis.bobPub
&& data.hello === 'mars'
&& data.crackers !== 'gonna crack'
&& undefined === data.crackers) {
test.done();
}
});
setTimeout(() => test.fail('timeout — pub-space read in 30s'), 30000);
}, { relayPort: config.relayPort });
}).then(() => {
return bob.run(async function (test) {
test.async();
if (!globalThis.user) { await require('./helpers/gunboot').bootGun(test.props.relayPort); }
user.val(function (data) {
if (data.hello === 'mars'
&& data.crackers !== 'gonna crack'
&& undefined === data.crackers) {
test.done();
}
});
setTimeout(() => test.fail('timeout — bob user-space read in 30s'), 30000);
}, { relayPort: config.relayPort });
});
});
after(function () {
teardownPanic();
});
});