Skip to content

Commit 575b879

Browse files
committed
test: add unit tests for event/profile view positional arg parsing
Export parsePositionalArgs from event/view.ts and profile/view.ts to enable unit testing. Add comprehensive tests covering: - Single argument (event ID or transaction only) - Two arguments (target + required arg) - Error cases (empty args) - Edge cases (extra args, empty strings)
1 parent 9f3adb3 commit 575b879

File tree

4 files changed

+192
-2
lines changed

4 files changed

+192
-2
lines changed

src/commands/event/view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const USAGE_HINT = "sentry event view <org>/<project> <event-id>";
7272
*
7373
* @returns Parsed event ID and optional target arg
7474
*/
75-
function parsePositionalArgs(args: string[]): {
75+
export function parsePositionalArgs(args: string[]): {
7676
eventId: string;
7777
targetArg: string | undefined;
7878
} {

src/commands/profile/view.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function parsePeriod(value: string): string {
6363
*
6464
* @returns Parsed transaction and optional target arg
6565
*/
66-
function parsePositionalArgs(args: string[]): {
66+
export function parsePositionalArgs(args: string[]): {
6767
transactionRef: string;
6868
targetArg: string | undefined;
6969
} {

test/commands/event/view.test.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Event View Command Tests
3+
*
4+
* Tests for positional argument parsing in src/commands/event/view.ts
5+
*/
6+
7+
import { describe, expect, test } from "bun:test";
8+
import { parsePositionalArgs } from "../../../src/commands/event/view.js";
9+
import { ContextError } from "../../../src/lib/errors.js";
10+
11+
describe("parsePositionalArgs", () => {
12+
describe("single argument (event ID only)", () => {
13+
test("parses single arg as event ID", () => {
14+
const result = parsePositionalArgs(["abc123def456"]);
15+
expect(result.eventId).toBe("abc123def456");
16+
expect(result.targetArg).toBeUndefined();
17+
});
18+
19+
test("parses UUID-like event ID", () => {
20+
const result = parsePositionalArgs([
21+
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
22+
]);
23+
expect(result.eventId).toBe("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
24+
expect(result.targetArg).toBeUndefined();
25+
});
26+
27+
test("parses short event ID", () => {
28+
const result = parsePositionalArgs(["abc"]);
29+
expect(result.eventId).toBe("abc");
30+
expect(result.targetArg).toBeUndefined();
31+
});
32+
});
33+
34+
describe("two arguments (target + event ID)", () => {
35+
test("parses org/project target and event ID", () => {
36+
const result = parsePositionalArgs(["my-org/frontend", "abc123def456"]);
37+
expect(result.targetArg).toBe("my-org/frontend");
38+
expect(result.eventId).toBe("abc123def456");
39+
});
40+
41+
test("parses project-only target and event ID", () => {
42+
const result = parsePositionalArgs(["frontend", "abc123def456"]);
43+
expect(result.targetArg).toBe("frontend");
44+
expect(result.eventId).toBe("abc123def456");
45+
});
46+
47+
test("parses org/ target (all projects) and event ID", () => {
48+
const result = parsePositionalArgs(["my-org/", "abc123def456"]);
49+
expect(result.targetArg).toBe("my-org/");
50+
expect(result.eventId).toBe("abc123def456");
51+
});
52+
});
53+
54+
describe("error cases", () => {
55+
test("throws ContextError for empty args", () => {
56+
expect(() => parsePositionalArgs([])).toThrow(ContextError);
57+
});
58+
59+
test("throws ContextError with usage hint", () => {
60+
try {
61+
parsePositionalArgs([]);
62+
expect.unreachable("Should have thrown");
63+
} catch (error) {
64+
expect(error).toBeInstanceOf(ContextError);
65+
expect((error as ContextError).message).toContain("Event ID");
66+
}
67+
});
68+
});
69+
70+
describe("edge cases", () => {
71+
test("handles more than two args (ignores extras)", () => {
72+
const result = parsePositionalArgs([
73+
"my-org/frontend",
74+
"abc123",
75+
"extra-arg",
76+
]);
77+
expect(result.targetArg).toBe("my-org/frontend");
78+
expect(result.eventId).toBe("abc123");
79+
});
80+
81+
test("handles empty string event ID in two-arg case", () => {
82+
const result = parsePositionalArgs(["my-org/frontend", ""]);
83+
expect(result.targetArg).toBe("my-org/frontend");
84+
expect(result.eventId).toBe("");
85+
});
86+
});
87+
});

test/commands/profile/view.test.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Profile View Command Tests
3+
*
4+
* Tests for positional argument parsing in src/commands/profile/view.ts
5+
*/
6+
7+
import { describe, expect, test } from "bun:test";
8+
import { parsePositionalArgs } from "../../../src/commands/profile/view.js";
9+
import { ContextError } from "../../../src/lib/errors.js";
10+
11+
describe("parsePositionalArgs", () => {
12+
describe("single argument (transaction only)", () => {
13+
test("parses single arg as transaction name", () => {
14+
const result = parsePositionalArgs(["/api/users"]);
15+
expect(result.transactionRef).toBe("/api/users");
16+
expect(result.targetArg).toBeUndefined();
17+
});
18+
19+
test("parses transaction index", () => {
20+
const result = parsePositionalArgs(["1"]);
21+
expect(result.transactionRef).toBe("1");
22+
expect(result.targetArg).toBeUndefined();
23+
});
24+
25+
test("parses transaction alias", () => {
26+
const result = parsePositionalArgs(["a"]);
27+
expect(result.transactionRef).toBe("a");
28+
expect(result.targetArg).toBeUndefined();
29+
});
30+
31+
test("parses complex transaction name", () => {
32+
const result = parsePositionalArgs(["POST /api/v2/users/:id/settings"]);
33+
expect(result.transactionRef).toBe("POST /api/v2/users/:id/settings");
34+
expect(result.targetArg).toBeUndefined();
35+
});
36+
});
37+
38+
describe("two arguments (target + transaction)", () => {
39+
test("parses org/project target and transaction name", () => {
40+
const result = parsePositionalArgs(["my-org/backend", "/api/users"]);
41+
expect(result.targetArg).toBe("my-org/backend");
42+
expect(result.transactionRef).toBe("/api/users");
43+
});
44+
45+
test("parses project-only target and transaction", () => {
46+
const result = parsePositionalArgs(["backend", "/api/users"]);
47+
expect(result.targetArg).toBe("backend");
48+
expect(result.transactionRef).toBe("/api/users");
49+
});
50+
51+
test("parses org/ target (all projects) and transaction", () => {
52+
const result = parsePositionalArgs(["my-org/", "/api/users"]);
53+
expect(result.targetArg).toBe("my-org/");
54+
expect(result.transactionRef).toBe("/api/users");
55+
});
56+
57+
test("parses target and transaction index", () => {
58+
const result = parsePositionalArgs(["my-org/backend", "1"]);
59+
expect(result.targetArg).toBe("my-org/backend");
60+
expect(result.transactionRef).toBe("1");
61+
});
62+
63+
test("parses target and transaction alias", () => {
64+
const result = parsePositionalArgs(["my-org/backend", "a"]);
65+
expect(result.targetArg).toBe("my-org/backend");
66+
expect(result.transactionRef).toBe("a");
67+
});
68+
});
69+
70+
describe("error cases", () => {
71+
test("throws ContextError for empty args", () => {
72+
expect(() => parsePositionalArgs([])).toThrow(ContextError);
73+
});
74+
75+
test("throws ContextError with usage hint", () => {
76+
try {
77+
parsePositionalArgs([]);
78+
expect.unreachable("Should have thrown");
79+
} catch (error) {
80+
expect(error).toBeInstanceOf(ContextError);
81+
expect((error as ContextError).message).toContain("Transaction");
82+
}
83+
});
84+
});
85+
86+
describe("edge cases", () => {
87+
test("handles more than two args (ignores extras)", () => {
88+
const result = parsePositionalArgs([
89+
"my-org/backend",
90+
"/api/users",
91+
"extra-arg",
92+
]);
93+
expect(result.targetArg).toBe("my-org/backend");
94+
expect(result.transactionRef).toBe("/api/users");
95+
});
96+
97+
test("handles empty string transaction in two-arg case", () => {
98+
const result = parsePositionalArgs(["my-org/backend", ""]);
99+
expect(result.targetArg).toBe("my-org/backend");
100+
expect(result.transactionRef).toBe("");
101+
});
102+
});
103+
});

0 commit comments

Comments
 (0)