mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-06-04 10:36:43 +00:00
749fdc114f
RED commit: `dc4c0800` — CI: https://github.com/Kpa-clawbot/CoreScope/actions?query=branch%3Afix%2Fissue-1279-p2 Closes the remaining six 🟢 P2 items in umbrella #1279 (PR #1280 shipped P0+P1, PR #1276 shipped ACK/RESPONSE/PATH legend rows). ### Item-by-item | # | Item | Where | Test | |---|---|---|---| | 1 | `payloadTypeNames` parity | `cmd/server/store.go` | `cmd/server/issue1279_p2_test.go::TestPayloadTypeNamesAll13` | | 2 | Legend rows: Anon Req / Grp Data / Multipart / Control / Raw Custom | `public/live.js` | `test-issue-1279-legend-p2-e2e.js` (Playwright) | | 3 | TransportCodes detail-row + `code1=` / `code2=` filter grammar | `public/packets.js`, `public/packet-filter.js` | `test-issue-1279-p2-code-filter.js` (6 cases) | | 4 | Multibyte capability badge on node detail/list rows | `public/nodes.js::renderNodeBadges` | `n.hash_size >= 2` (observable Feat1/Feat2 proxy; firmware `AdvertDataHelpers.h:14-16`) | | 5 | RAW_CUSTOM (0x0F) `{rawLength, firstByteTag}` decode + detail-row | `cmd/server/decoder.go`, `cmd/ingestor/decoder.go`, `public/packets.js` | `TestDecodeRawCustomExposesLengthAndTag` × 2 + updated `TestDecodePayloadRAWCustom` | | 6 | Sensor advert telemetry firmware-derivation comments | `cmd/ingestor/decoder.go:363-380` | pure comments — exempt per AGENTS | ### Firmware refs cited inline - `firmware/src/Packet.h:19-32` — PAYLOAD_TYPE_* constants - `firmware/src/Packet.h:46` — TransportCodes wire layout - `firmware/src/Mesh.cpp:577` — `createRawData` - `firmware/src/helpers/SensorMesh.{h,cpp}` — sensor advert telemetry derivation - `firmware/src/helpers/AdvertDataHelpers.h:14-16` — Feat1/Feat2 ### TDD Red `dc4c0800` proves the assertions gate behavior: - `payloadTypeNames` had only 12 entries (no 0x0F). - RAW_CUSTOM decoded as `UNKNOWN` with no envelope fields. Green `<HEAD>` makes both green; per-item tests included. ### Cross-stack note Cross-stack: justified — items 1/5 add decoder output fields; items 2/3/4/5 surface those fields in the UI in the same PR per #1279 acceptance. ### Out of scope Item 4 surfaces the observable multibyte capability via the persisted `hash_size` (Feat1/Feat2 wire bits are only on transient adverts and not stored per-node today); persisting raw Feat1/Feat2 per-node is left for a follow-up. Fixes #1279 --------- Co-authored-by: bot <bot@corescope>
76 lines
2.7 KiB
JavaScript
76 lines
2.7 KiB
JavaScript
/**
|
|
* E2E for #1279 P2 #2 — Live legend covers all remaining named payload types.
|
|
* After PR #1276 the legend already lists Advert/Message/Direct/Request/
|
|
* Response/Trace/Path/Ack; this PR adds Anon Req, Grp Data, Multipart,
|
|
* Control and Raw Custom.
|
|
*
|
|
* Run: BASE_URL=http://localhost:13581 node test-issue-1279-legend-p2-e2e.js
|
|
*/
|
|
'use strict';
|
|
const { chromium } = require('playwright');
|
|
|
|
const BASE = process.env.BASE_URL || 'http://localhost:13581';
|
|
|
|
let passed = 0, failed = 0;
|
|
async function step(name, fn) {
|
|
try { await fn(); passed++; console.log(' ✓ ' + name); }
|
|
catch (e) { failed++; console.error(' ✗ ' + name + ': ' + e.message); }
|
|
}
|
|
function assert(c, m) { if (!c) throw new Error(m || 'assertion failed'); }
|
|
|
|
async function gotoLive(page) {
|
|
await page.goto(BASE + '/#/live', { waitUntil: 'domcontentloaded' });
|
|
await page.waitForSelector('#liveLegend', { timeout: 8000, state: 'attached' });
|
|
await page.waitForTimeout(400);
|
|
const hidden = await page.evaluate(() => {
|
|
const el = document.getElementById('liveLegend');
|
|
return !!el && el.classList.contains('hidden');
|
|
});
|
|
if (hidden) {
|
|
await page.evaluate(() => {
|
|
try { localStorage.removeItem('live-legend-hidden'); } catch (_) {}
|
|
const el = document.getElementById('liveLegend');
|
|
if (el) el.classList.remove('hidden');
|
|
});
|
|
}
|
|
}
|
|
|
|
async function legendText(page) {
|
|
return page.evaluate(() => {
|
|
const el = document.getElementById('liveLegend');
|
|
return el ? (el.textContent || '').toLowerCase() : '';
|
|
});
|
|
}
|
|
|
|
(async () => {
|
|
const browser = await chromium.launch({
|
|
headless: true,
|
|
executablePath: process.env.CHROMIUM_PATH || undefined,
|
|
args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage'],
|
|
});
|
|
|
|
console.log(`\n=== #1279 P2 legend covers all 13 payload types — E2E against ${BASE} ===`);
|
|
|
|
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
|
|
const page = await ctx.newPage();
|
|
page.setDefaultTimeout(8000);
|
|
page.on('pageerror', (e) => console.error('[pageerror]', e.message));
|
|
|
|
await step('navigate to /live', async () => { await gotoLive(page); });
|
|
|
|
// Types already covered by #1274/#1276: Advert/Message/Direct/Request/
|
|
// Response/Trace/Path/Ack. New ones added by #1279 P2:
|
|
const newRows = ['anon req', 'grp data', 'multipart', 'control', 'raw custom'];
|
|
for (const label of newRows) {
|
|
await step(`legend lists "${label}"`, async () => {
|
|
const t = await legendText(page);
|
|
assert(t.indexOf(label) !== -1, 'legend missing row: ' + label);
|
|
});
|
|
}
|
|
|
|
await ctx.close();
|
|
await browser.close();
|
|
console.log(`\n=== ${passed} passed, ${failed} failed ===`);
|
|
process.exit(failed === 0 ? 0 : 1);
|
|
})().catch((e) => { console.error(e); process.exit(1); });
|