test: close test gaps for #123 decrypted status and #131 WS handler runtime

Gap 1 (#123): Add 3 decoder tests for GRP_TXT decrypted status path.
Mock ChannelCrypto via require.cache to simulate successful decryption.
Tests cover: sender+message formatting, no-sender fallback, multi-key
iteration with first-match-wins semantics.

Gap 2 (#131): Rewrite 5 src.includes() string-match tests as runtime
vm.createContext tests. New makeNodesWsSandbox() helper with controllable
setTimeout, mock DOM, tracked API/cache calls, and real debouncedOnWS.
Tests verify: ADVERT triggers refresh, non-ADVERT ignored, debounce
collapses multiple ADVERTs, cache reset forces re-fetch, scroll/selection
preserved during WS-triggered refresh.

Decoder: 58 -> 61 tests. Frontend helpers: 87 (5 replaced, not added).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Kpa-clawbot
2026-03-27 08:47:52 -07:00
parent 3cd6cb98fa
commit 1137dd1c08
3 changed files with 259 additions and 50 deletions

View File

@@ -247,6 +247,100 @@ test('GRP_TXT decryptionStatus is no_key when encrypted data too short', () => {
assert.strictEqual(p.payload.decryptionStatus, 'no_key');
});
test('GRP_TXT decryptionStatus is decrypted when key matches', () => {
// Mock the ChannelCrypto module to simulate successful decryption
const cryptoPath = require.resolve('@michaelhart/meshcore-decoder/dist/crypto/channel-crypto');
const originalModule = require.cache[cryptoPath];
require.cache[cryptoPath] = {
id: cryptoPath,
exports: {
ChannelCrypto: {
decryptGroupTextMessage: () => ({
success: true,
data: { sender: 'TestUser', message: 'Hello world', timestamp: 1700000000, flags: 0 },
}),
},
},
};
try {
const hex = '1500' + 'FF' + 'AABB' + 'CCDDEE112233';
const p = decodePacket(hex, { '#general': 'aabbccddaabbccddaabbccddaabbccdd' });
assert.strictEqual(p.payload.decryptionStatus, 'decrypted');
assert.strictEqual(p.payload.type, 'CHAN');
assert.strictEqual(p.payload.channelHashHex, 'FF');
assert.strictEqual(p.payload.channel, '#general');
assert.strictEqual(p.payload.sender, 'TestUser');
assert.strictEqual(p.payload.text, 'TestUser: Hello world');
assert.strictEqual(p.payload.sender_timestamp, 1700000000);
assert.strictEqual(p.payload.flags, 0);
assert.strictEqual(p.payload.channelHash, 0xFF);
} finally {
if (originalModule) require.cache[cryptoPath] = originalModule;
else delete require.cache[cryptoPath];
}
});
test('GRP_TXT decrypted without sender formats text correctly', () => {
const cryptoPath = require.resolve('@michaelhart/meshcore-decoder/dist/crypto/channel-crypto');
const originalModule = require.cache[cryptoPath];
require.cache[cryptoPath] = {
id: cryptoPath,
exports: {
ChannelCrypto: {
decryptGroupTextMessage: () => ({
success: true,
data: { sender: null, message: 'Broadcast msg', timestamp: 1700000001, flags: 1 },
}),
},
},
};
try {
const hex = '1500' + '0A' + 'AABB' + 'CCDDEE112233';
const p = decodePacket(hex, { '#alerts': 'deadbeefdeadbeefdeadbeefdeadbeef' });
assert.strictEqual(p.payload.decryptionStatus, 'decrypted');
assert.strictEqual(p.payload.sender, null);
assert.strictEqual(p.payload.text, 'Broadcast msg');
assert.strictEqual(p.payload.channelHashHex, '0A');
} finally {
if (originalModule) require.cache[cryptoPath] = originalModule;
else delete require.cache[cryptoPath];
}
});
test('GRP_TXT decrypted tries multiple keys, first match wins', () => {
const cryptoPath = require.resolve('@michaelhart/meshcore-decoder/dist/crypto/channel-crypto');
const originalModule = require.cache[cryptoPath];
let callCount = 0;
require.cache[cryptoPath] = {
id: cryptoPath,
exports: {
ChannelCrypto: {
decryptGroupTextMessage: (ciphertext, mac, key) => {
callCount++;
if (key === 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb') {
return { success: true, data: { sender: 'Bob', message: 'Found it', timestamp: 0, flags: 0 } };
}
return { success: false };
},
},
},
};
try {
const hex = '1500' + 'FF' + 'AABB' + 'CCDDEE112233';
const p = decodePacket(hex, {
'#wrong': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'#right': 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
});
assert.strictEqual(p.payload.decryptionStatus, 'decrypted');
assert.strictEqual(p.payload.channel, '#right');
assert.strictEqual(p.payload.sender, 'Bob');
assert.strictEqual(callCount, 2);
} finally {
if (originalModule) require.cache[cryptoPath] = originalModule;
else delete require.cache[cryptoPath];
}
});
console.log('\n=== TXT_MSG payload ===');
test('TXT_MSG decode', () => {
// payloadType=2 → (2<<2)|1 = 0x09