diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-27 21:55:44 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-27 21:55:44 +0200 |
| commit | 89e864669d62a88f337c02d2097de4afb37e6333 (patch) | |
| tree | 38d0034de8a3bca44a2d8af616e58c19f4ddf02a /internal/flamegraph/livehtml_interaction_test.go | |
| parent | 281a433b9ff39c0b290adfc901bdf47cc486491f (diff) | |
flamegraph: add live field-order toggle and reconfigure API
Diffstat (limited to 'internal/flamegraph/livehtml_interaction_test.go')
| -rw-r--r-- | internal/flamegraph/livehtml_interaction_test.go | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/internal/flamegraph/livehtml_interaction_test.go b/internal/flamegraph/livehtml_interaction_test.go index 675b03f..0de1466 100644 --- a/internal/flamegraph/livehtml_interaction_test.go +++ b/internal/flamegraph/livehtml_interaction_test.go @@ -40,6 +40,12 @@ type resetBaselineResult struct { ResetCallsValid bool `json:"resetCallsValid"` } +type orderToggleResult struct { + OrderButtonUpdated bool `json:"orderButtonUpdated"` + OrderCallValid bool `json:"orderCallValid"` + OrderSnapshotShown bool `json:"orderSnapshotShown"` +} + func TestLiveHTMLJSZoomSearchStatePreservedAcrossUpdates(t *testing.T) { if _, err := exec.LookPath("node"); err != nil { t.Skip("node not available") @@ -389,6 +395,78 @@ setTimeout(function() { } } +func TestLiveHTMLJSOrderToggle(t *testing.T) { + if _, err := exec.LookPath("node"); err != nil { + t.Skip("node not available") + } + + snippet := ` +const fg = liveFlamegraphState; +const orderCalls = []; +fetch = function(url, opts) { + orderCalls.push({ + url: url, + method: (opts && opts.method) || "GET", + body: (opts && opts.body) || "" + }); + return Promise.resolve({ + ok: true, + json: function() { + return Promise.resolve({ + fields: ["path", "tracepoint", "comm"], + snapshot: { + n: "", + v: 0, + t: 1, + c: [{ n: "/tmp", v: 1, t: 1 }] + } + }); + } + }); +}; + +document.getElementById("btn-toggle-order").listeners.click(); + +setTimeout(function() { + const orderButtonUpdated = document.getElementById("btn-toggle-order").textContent.indexOf("path > tracepoint > comm") >= 0; + const orderSnapshotShown = fg.svg.innerHTML.indexOf('data-name="/tmp"') >= 0; + const req = orderCalls[0] || {}; + let bodyFields = []; + try { + bodyFields = JSON.parse(req.body || "{}").fields || []; + } catch (err) { + bodyFields = []; + } + const orderCallValid = orderCalls.length === 1 && + req.url === "/order" && + req.method === "POST" && + JSON.stringify(bodyFields) === JSON.stringify(["path", "tracepoint", "comm"]); + + console.log(JSON.stringify({ + orderButtonUpdated, + orderCallValid, + orderSnapshotShown + })); +}, 0); +` + + out := runLiveHTMLNodeSnippet(t, snippet) + var got orderToggleResult + if err := json.Unmarshal([]byte(out), &got); err != nil { + t.Fatalf("decode node result: %v\nraw:\n%s", err, out) + } + + if !got.OrderButtonUpdated { + t.Fatalf("expected toggle button label to update to next order") + } + if !got.OrderCallValid { + t.Fatalf("expected toggle to POST /order with next preset fields") + } + if !got.OrderSnapshotShown { + t.Fatalf("expected returned order snapshot to render immediately") + } +} + func runLiveHTMLNodeSnippet(t *testing.T, snippet string) string { t.Helper() @@ -477,7 +555,7 @@ function makeFrame(name, path, depth, x, w) { } const elements = {}; -["controls", "flamegraph", "status", "btn-pause", "btn-search", "btn-reset-search", "btn-undo-zoom", "btn-reset-zoom", "btn-reset-baseline"].forEach((id) => { +["controls", "flamegraph", "status", "btn-pause", "btn-search", "btn-reset-search", "btn-undo-zoom", "btn-reset-zoom", "btn-reset-baseline", "btn-toggle-order"].forEach((id) => { elements[id] = makeElement(id); }); elements["body"] = makeElement("body"); @@ -493,6 +571,13 @@ global.document = { }; global.window = global; global.prompt = function(){ return ""; }; +global.fetch = function() { + return Promise.resolve({ + ok: true, + json: function() { return Promise.resolve({ fields: ["comm", "path", "tracepoint"], snapshot: { n: "", v: 0, t: 0 } }); }, + text: function() { return Promise.resolve("{\"n\":\"\",\"v\":0,\"t\":0}"); } + }); +}; global.requestAnimationFrame = function(cb){ cb(); }; global.EventSource = function() { this.onmessage = null; |
