From 39dcfd7307299a47942fabbf1487b233fadf8a84 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Thu, 28 May 2026 22:07:51 -0300 Subject: [PATCH] feat(inspector-ui): expose pendingCount for X-new badge during pause (R5-9) --- .../components/TopBarControls.tsx | 7 ++++ src/i18n/messages/en.json | 4 ++- src/i18n/messages/pt-BR.json | 4 ++- tests/unit/ui/use-traffic-stream.test.tsx | 34 +++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/TopBarControls.tsx b/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/TopBarControls.tsx index b2eef480f2..03ff373ee4 100644 --- a/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/TopBarControls.tsx +++ b/src/app/(dashboard)/dashboard/tools/traffic-inspector/components/TopBarControls.tsx @@ -27,6 +27,7 @@ interface TopBarControlsProps { connected: boolean; total: number; maxSize?: number; + pendingCount?: number; // session recorder recording: boolean; session: SessionInfo | null; @@ -53,6 +54,7 @@ export function TopBarControls({ connected, total, maxSize = 1000, + pendingCount = 0, recording, session, elapsed, @@ -188,6 +190,11 @@ export function TopBarControls({ {total}/{maxSize} + {paused && pendingCount > 0 && ( + + {t("pausedNewBadge", { count: pendingCount })} + + )} diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 7123a1ccd5..a7025e3c86 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -7488,6 +7488,8 @@ "timingMethod": "Method", "timingStatus": "Status", "timingRequestSize": "Request size", - "timingResponseSize": "Response size" + "timingResponseSize": "Response size", + "pausedNewBadge": "{count} new", + "clearContextFilter": "clear" } } diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 2219e32eb9..ffcf810acc 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -7478,6 +7478,8 @@ "timingMethod": "Método", "timingStatus": "Status", "timingRequestSize": "Tamanho da requisição", - "timingResponseSize": "Tamanho da resposta" + "timingResponseSize": "Tamanho da resposta", + "pausedNewBadge": "{count} novos", + "clearContextFilter": "limpar" } } diff --git a/tests/unit/ui/use-traffic-stream.test.tsx b/tests/unit/ui/use-traffic-stream.test.tsx index 6959e2cdd1..ce8804fa9b 100644 --- a/tests/unit/ui/use-traffic-stream.test.tsx +++ b/tests/unit/ui/use-traffic-stream.test.tsx @@ -3,6 +3,18 @@ */ import { describe, it, before, after, mock } from "node:test"; import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const HOOK_SRC = fs.readFileSync( + path.resolve( + __dirname, + "../../../src/app/(dashboard)/dashboard/tools/traffic-inspector/hooks/useTrafficStream.ts" + ), + "utf8" +); // Minimal EventEmitter-based mock WebSocket class MockWebSocket { @@ -165,4 +177,26 @@ describe("useTrafficStream core logic", () => { assert.equal(pending.length, 1); assert.equal(pending[0].id, "3"); }); + + it("TrafficStreamState interface includes pendingCount field (R5-9)", () => { + assert.ok( + HOOK_SRC.includes("pendingCount"), + "TrafficStreamState should expose pendingCount" + ); + }); + + it("pendingCount increments when paused and new event arrives (R5-9)", () => { + // Verify the source contains the setPendingCount call when pushing to pendingRef + assert.ok( + HOOK_SRC.includes("setPendingCount(pendingRef.current.length)"), + "should call setPendingCount when adding to pendingRef" + ); + }); + + it("pendingCount resets to 0 on resume (R5-9)", () => { + assert.ok( + HOOK_SRC.includes("setPendingCount(0)"), + "should reset pendingCount to 0 on resume and clear" + ); + }); });