mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-09-02 00:58:21 +00:00
feat: decrypted channel messages, scopes in ws
This commit is contained in:
@@ -301,16 +301,15 @@ function GroupTextPayload({ payload }: PayloadProps) {
|
||||
<span className="text-text-normal font-semibold">{String(decrypted.sender)}</span>
|
||||
</div>
|
||||
)}
|
||||
{decrypted.message != null && (
|
||||
{decrypted.content != null && (
|
||||
<div>
|
||||
<span className="text-text-dim">Message </span>
|
||||
<span className="text-text-bright break-all">{String(decrypted.message)}</span>
|
||||
<span className="text-text-bright break-all">{String(decrypted.content)}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex gap-x-4 text-text-dim">
|
||||
{decrypted.timestamp != null && <span>{formatUnixTs(decrypted.timestamp as number)}</span>}
|
||||
{decrypted.flags != null && <span>Flags {String(decrypted.flags)}</span>}
|
||||
</div>
|
||||
{decrypted.sentAt != null && (
|
||||
<div className="text-text-dim">{formatTimestamp(decrypted.sentAt as number)}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -143,6 +143,7 @@ export function usePackets() {
|
||||
firstHeardAt: data.observation.heardAt,
|
||||
lastHeardAt: data.observation.heardAt,
|
||||
observationCount: data.packet.observationCount,
|
||||
scope: data.packet.scope,
|
||||
latestObserver: {
|
||||
id: data.observation.observerId,
|
||||
displayName: data.observation.observerName,
|
||||
|
||||
@@ -41,6 +41,7 @@ export interface WsPacketObservation {
|
||||
routeTypeName: string;
|
||||
isFirstObservation: boolean;
|
||||
observationCount: number;
|
||||
scope?: string; // matched transport scope name; omitted when none matched
|
||||
};
|
||||
observation: {
|
||||
observerId: string;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { render, screen, fireEvent } from "@testing-library/react";
|
||||
import { PayloadBreakdown } from "../../../src/features/packets/payload-renderers";
|
||||
import { formatTimestamp } from "../../../src/lib/formatters";
|
||||
import type { ResolvedHop } from "../../../src/types/api";
|
||||
|
||||
const tracePayload = {
|
||||
@@ -44,3 +45,30 @@ describe("PayloadBreakdown — trace resolvedRoute overlay", () => {
|
||||
expect(screen.getByText("-")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe("PayloadBreakdown — GROUP_TEXT decrypted channel message", () => {
|
||||
// Backend GetPacket enrichment nests decrypted:{sender,content,sentAt} (sentAt is epoch ms).
|
||||
// See tower-server db/packets.go + internal/ingest/side_effects.go.
|
||||
// chosen so the ms reading (5:43 p.m.) and the wrong seconds reading (1:13 p.m.) differ
|
||||
const sentAt = 1_700_001_800_000; // epoch ms
|
||||
const payload = {
|
||||
type: "GROUP_TEXT",
|
||||
channelHash: "ab",
|
||||
cipherMac: "00112233",
|
||||
ciphertext: "deadbeef",
|
||||
decrypted: { sender: "Alice", content: "hello mesh", sentAt },
|
||||
};
|
||||
|
||||
it("renders the decrypted sender and message body from content", () => {
|
||||
render(<PayloadBreakdown payload={payload} />);
|
||||
expect(screen.getByText("Alice")).toBeInTheDocument();
|
||||
expect(screen.getByText("hello mesh")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("formats sentAt as epoch milliseconds, not seconds", () => {
|
||||
render(<PayloadBreakdown payload={payload} />);
|
||||
expect(screen.getByText(formatTimestamp(sentAt))).toBeInTheDocument();
|
||||
// the seconds interpretation (×1000) would be a far-future date — must not appear
|
||||
expect(screen.queryByText(formatTimestamp(sentAt * 1000))).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user