mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
test(replay-ui): pin action selector parse and row formatting
This commit is contained in:
1 parent
a4d6020663
commit
3fa52b3a65
1 file changed
+84
@@ -0,0 +1,84 @@
|
|||||||
|
import { describe, it, expect } from "bun:test";
|
||||||
|
import {
|
||||||
|
formatActionRow,
|
||||||
|
formatElapsed,
|
||||||
|
parseSelector,
|
||||||
|
tagFromSelector,
|
||||||
|
} from "../lib/action-format";
|
||||||
|
import type { StepSummary } from "../types";
|
||||||
|
|
||||||
|
function summary(over: Partial<StepSummary>): StepSummary {
|
||||||
|
return {
|
||||||
|
index: 0,
|
||||||
|
timestamp: "1970-01-01T00:00:00.000Z",
|
||||||
|
has_violations: false,
|
||||||
|
has_exceptions: false,
|
||||||
|
...over,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bug class: selector parsing mislabels every action row — splitting on the
|
||||||
|
// wrong colon, treating a value-with-colon as the kind, or dropping the prefix
|
||||||
|
// ellipsis would render the wrong target tag for every step.
|
||||||
|
describe("parseSelector", () => {
|
||||||
|
const cases: { input: string; out: ReturnType<typeof parseSelector> }[] = [
|
||||||
|
{ input: "id:login", out: { kind: "id", value: "login" } },
|
||||||
|
{ input: "text:Sign In", out: { kind: "text", value: "Sign In" } },
|
||||||
|
{ input: "textPrefix:Hello", out: { kind: "textPrefix", value: "Hello" } },
|
||||||
|
{ input: "id:com.app:id/btn", out: { kind: "id", value: "com.app:id/btn" } },
|
||||||
|
{ input: "bogus:x", out: null },
|
||||||
|
{ input: ":leading", out: null },
|
||||||
|
{ input: "no-colon", out: null },
|
||||||
|
];
|
||||||
|
for (const { input, out } of cases) {
|
||||||
|
it(`parses ${input}`, () => {
|
||||||
|
expect(parseSelector(input)).toEqual(out);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("tagFromSelector", () => {
|
||||||
|
it("appends ellipsis only for prefix selectors", () => {
|
||||||
|
expect(tagFromSelector("textPrefix:Hel")).toBe("Hel...");
|
||||||
|
expect(tagFromSelector("text:Hello")).toBe("Hello");
|
||||||
|
expect(tagFromSelector("plain")).toBe("plain");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formatActionRow", () => {
|
||||||
|
it("observes when no action kind, with and without screen", () => {
|
||||||
|
expect(formatActionRow(summary({}))).toEqual({
|
||||||
|
verb: "Observe",
|
||||||
|
target: "",
|
||||||
|
targetIsTag: false,
|
||||||
|
});
|
||||||
|
expect(formatActionRow(summary({ screen: "Home" }))).toEqual({
|
||||||
|
verb: "Observe",
|
||||||
|
target: "@ Home",
|
||||||
|
targetIsTag: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("treats a selector label as a tag and a coordinate label as literal", () => {
|
||||||
|
expect(
|
||||||
|
formatActionRow(summary({ action_kind: "Tap", action_label: "id:btn" })),
|
||||||
|
).toEqual({ verb: "Click", target: "btn", targetIsTag: true });
|
||||||
|
expect(
|
||||||
|
formatActionRow(summary({ action_kind: "Tap", action_label: "(10, 20)" })),
|
||||||
|
).toEqual({ verb: "Click", target: "(10, 20)", targetIsTag: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maps known verbs and falls back to the raw kind", () => {
|
||||||
|
expect(formatActionRow(summary({ action_kind: "InputText", action_label: "hi" })).verb).toBe("Type");
|
||||||
|
expect(formatActionRow(summary({ action_kind: "Swipe" })).verb).toBe("Swipe");
|
||||||
|
expect(formatActionRow(summary({ action_kind: "Custom" })).verb).toBe("Custom");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("formatElapsed", () => {
|
||||||
|
it("formats mm:ss.mmm and clamps negatives to zero", () => {
|
||||||
|
expect(formatElapsed(0)).toBe("00:00.000");
|
||||||
|
expect(formatElapsed(65_432)).toBe("01:05.432");
|
||||||
|
expect(formatElapsed(-50)).toBe("00:00.000");
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user