Skip to content

Commit fc146ae

Browse files
fix(test): adapt tests for buildCommand auth guard (#611)
The auth guard added in #611 calls getAuthConfig() before every command, which broke ~200 tests that had no auth token in the test environment. - Set a fake SENTRY_AUTH_TOKEN in test preload so the auth guard passes globally (real API calls are blocked by the global fetch mock) - Add auth: false to command.test.ts test commands (they test framework behavior, not authentication) - Clear the env token in tests that specifically verify unauthenticated or SENTRY_TOKEN-priority behavior (logout, refresh, whoami, project list)
1 parent e36a421 commit fc146ae

File tree

6 files changed

+95
-10
lines changed

6 files changed

+95
-10
lines changed

test/commands/auth/logout.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ describe("logoutCommand.func", () => {
126126
isAuthenticatedSpy.mockReturnValue(true);
127127
isEnvTokenActiveSpy.mockReturnValue(true);
128128
// Set env var directly — getActiveEnvVarName() reads env vars via getEnvToken()
129+
// Clear SENTRY_AUTH_TOKEN so SENTRY_TOKEN takes priority
130+
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
131+
delete process.env.SENTRY_AUTH_TOKEN;
129132
process.env.SENTRY_TOKEN = "sntrys_token_456";
130133
const { context } = createContext();
131134

@@ -138,6 +141,9 @@ describe("logoutCommand.func", () => {
138141
expect(msg).toContain("SENTRY_TOKEN");
139142
} finally {
140143
delete process.env.SENTRY_TOKEN;
144+
if (savedAuthToken !== undefined) {
145+
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
146+
}
141147
}
142148
expect(clearAuthSpy).not.toHaveBeenCalled();
143149
});

test/commands/auth/refresh.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ describe("refreshCommand.func", () => {
8585
test("env token (SENTRY_TOKEN): throws AuthError with SENTRY_TOKEN in message", async () => {
8686
isEnvTokenActiveSpy.mockReturnValue(true);
8787
// Set env var directly — getActiveEnvVarName() reads env vars via getEnvToken()
88+
// Clear SENTRY_AUTH_TOKEN so SENTRY_TOKEN takes priority
89+
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
90+
delete process.env.SENTRY_AUTH_TOKEN;
8891
process.env.SENTRY_TOKEN = "sntrys_token_456";
8992

9093
const { context } = createContext();
@@ -99,6 +102,9 @@ describe("refreshCommand.func", () => {
99102
expect((err as AuthError).message).not.toContain("SENTRY_AUTH_TOKEN");
100103
} finally {
101104
delete process.env.SENTRY_TOKEN;
105+
if (savedAuthToken !== undefined) {
106+
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
107+
}
102108
}
103109

104110
expect(refreshTokenSpy).not.toHaveBeenCalled();

test/commands/auth/whoami.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,26 @@ describe("whoamiCommand.func", () => {
8484
});
8585

8686
describe("unauthenticated", () => {
87+
let getAuthConfigSpy: ReturnType<typeof spyOn>;
88+
let savedAuthToken: string | undefined;
89+
90+
beforeEach(() => {
91+
// Clear env token and mock getAuthConfig so buildCommand's auth guard
92+
// sees no credentials — this tests the unauthenticated path end-to-end.
93+
savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
94+
delete process.env.SENTRY_AUTH_TOKEN;
95+
getAuthConfigSpy = spyOn(dbAuth, "getAuthConfig").mockReturnValue(
96+
undefined
97+
);
98+
});
99+
100+
afterEach(() => {
101+
getAuthConfigSpy.mockRestore();
102+
if (savedAuthToken !== undefined) {
103+
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
104+
}
105+
});
106+
87107
test("throws AuthError(not_authenticated) when no token stored", async () => {
88108
isAuthenticatedSpy.mockReturnValue(false);
89109

test/commands/project/list.test.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,17 @@ describe("fetchOrgProjectsSafe", () => {
969969
test("propagates AuthError when not authenticated", async () => {
970970
// Clear auth token so the API client throws AuthError before making any request
971971
await clearAuth();
972-
973-
await expect(fetchOrgProjectsSafe("myorg")).rejects.toThrow(AuthError);
972+
// Also clear env token — preload sets a fake one for the auth guard
973+
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
974+
delete process.env.SENTRY_AUTH_TOKEN;
975+
976+
try {
977+
await expect(fetchOrgProjectsSafe("myorg")).rejects.toThrow(AuthError);
978+
} finally {
979+
if (savedAuthToken !== undefined) {
980+
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
981+
}
982+
}
974983
});
975984
});
976985

@@ -1233,14 +1242,23 @@ describe("handleAutoDetect", () => {
12331242
setDefaults("test-org");
12341243
// Clear auth so getAuthToken() throws AuthError before any fetch
12351244
await clearAuth();
1236-
1237-
await expect(
1238-
handleAutoDetect("/tmp/test-project", {
1239-
limit: 30,
1240-
json: true,
1241-
fresh: false,
1242-
})
1243-
).rejects.toThrow(AuthError);
1245+
// Also clear env token — preload sets a fake one for the auth guard
1246+
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
1247+
delete process.env.SENTRY_AUTH_TOKEN;
1248+
1249+
try {
1250+
await expect(
1251+
handleAutoDetect("/tmp/test-project", {
1252+
limit: 30,
1253+
json: true,
1254+
fresh: false,
1255+
})
1256+
).rejects.toThrow(AuthError);
1257+
} finally {
1258+
if (savedAuthToken !== undefined) {
1259+
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
1260+
}
1261+
}
12441262
});
12451263

12461264
test("slow path: uses full fetch when platform filter is active", async () => {

test/lib/command.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ describe("buildCommand", () => {
7676
test("builds a valid command object", () => {
7777
const command = buildCommand({
7878
docs: { brief: "Test command" },
79+
auth: false,
7980
parameters: {
8081
flags: {
8182
verbose: { kind: "boolean", brief: "Verbose", default: false },
@@ -91,6 +92,7 @@ describe("buildCommand", () => {
9192
test("handles commands with empty parameters", () => {
9293
const command = buildCommand({
9394
docs: { brief: "Simple command" },
95+
auth: false,
9496
parameters: {},
9597
async *func() {
9698
// no-op
@@ -128,6 +130,7 @@ describe("buildCommand telemetry integration", () => {
128130
TestContext
129131
>({
130132
docs: { brief: "Test" },
133+
auth: false,
131134
parameters: {
132135
flags: {
133136
verbose: { kind: "boolean", brief: "Verbose", default: false },
@@ -168,6 +171,7 @@ describe("buildCommand telemetry integration", () => {
168171
test("skips false boolean flags in telemetry", async () => {
169172
const command = buildCommand<{ json: boolean }, [], TestContext>({
170173
docs: { brief: "Test" },
174+
auth: false,
171175
parameters: {
172176
flags: {
173177
json: { kind: "boolean", brief: "JSON output", default: false },
@@ -199,6 +203,7 @@ describe("buildCommand telemetry integration", () => {
199203

200204
const command = buildCommand<Record<string, never>, [string], TestContext>({
201205
docs: { brief: "Test" },
206+
auth: false,
202207
parameters: {
203208
positional: {
204209
kind: "tuple",
@@ -236,6 +241,7 @@ describe("buildCommand telemetry integration", () => {
236241

237242
const command = buildCommand<Record<string, never>, [], TestContext>({
238243
docs: { brief: "Test" },
244+
auth: false,
239245
parameters: {},
240246
// biome-ignore lint/correctness/useYield: test command — no output to yield
241247
async *func(this: TestContext) {
@@ -261,6 +267,7 @@ describe("buildCommand telemetry integration", () => {
261267

262268
const command = buildCommand<{ delay: number }, [], TestContext>({
263269
docs: { brief: "Test" },
270+
auth: false,
264271
parameters: {
265272
flags: {
266273
delay: {
@@ -371,6 +378,7 @@ describe("buildCommand", () => {
371378
test("builds a valid command object", () => {
372379
const command = buildCommand({
373380
docs: { brief: "Test command" },
381+
auth: false,
374382
parameters: {
375383
flags: {
376384
json: { kind: "boolean", brief: "JSON output", default: false },
@@ -388,6 +396,7 @@ describe("buildCommand", () => {
388396

389397
const command = buildCommand<{ json: boolean }, [], TestContext>({
390398
docs: { brief: "Test" },
399+
auth: false,
391400
parameters: {
392401
flags: {
393402
json: { kind: "boolean", brief: "JSON output", default: false },
@@ -499,6 +508,7 @@ describe("buildCommand", () => {
499508

500509
const command = buildCommand<{ limit: number }, [], TestContext>({
501510
docs: { brief: "Test" },
511+
auth: false,
502512
parameters: {
503513
flags: {
504514
limit: {
@@ -547,6 +557,7 @@ describe("buildCommand", () => {
547557
TestContext
548558
>({
549559
docs: { brief: "Test" },
560+
auth: false,
550561
parameters: {
551562
flags: {
552563
verbose: {
@@ -603,6 +614,7 @@ describe("buildCommand", () => {
603614
try {
604615
const command = buildCommand<{ verbose: boolean }, [], TestContext>({
605616
docs: { brief: "Test" },
617+
auth: false,
606618
parameters: {
607619
flags: {
608620
verbose: {
@@ -674,6 +686,7 @@ describe("buildCommand output config", () => {
674686
TestContext
675687
>({
676688
docs: { brief: "Test" },
689+
auth: false,
677690
output: { human: () => "unused" },
678691
parameters: {
679692
flags: {
@@ -717,6 +730,7 @@ describe("buildCommand output config", () => {
717730
TestContext
718731
>({
719732
docs: { brief: "Test" },
733+
auth: false,
720734
output: { human: () => "unused" },
721735
parameters: {},
722736
// biome-ignore lint/correctness/useYield: test command — no output to yield
@@ -756,6 +770,7 @@ describe("buildCommand output config", () => {
756770
TestContext
757771
>({
758772
docs: { brief: "Test" },
773+
auth: false,
759774
output: { human: () => "unused" },
760775
parameters: {},
761776
// biome-ignore lint/correctness/useYield: test command — no output to yield
@@ -794,6 +809,7 @@ describe("buildCommand output config", () => {
794809
TestContext
795810
>({
796811
docs: { brief: "Test" },
812+
auth: false,
797813
output: { human: () => "unused" },
798814
parameters: {},
799815
// biome-ignore lint/correctness/useYield: test command — no output to yield
@@ -858,6 +874,7 @@ describe("buildCommand output config", () => {
858874
TestContext
859875
>({
860876
docs: { brief: "Test" },
877+
auth: false,
861878
output: { human: () => "unused" },
862879
parameters: {
863880
flags: {
@@ -901,6 +918,7 @@ describe("buildCommand output config", () => {
901918
TestContext
902919
>({
903920
docs: { brief: "Test" },
921+
auth: false,
904922
output: { human: () => "unused" },
905923
parameters: {},
906924
// biome-ignore lint/correctness/useYield: test command — no output to yield
@@ -942,6 +960,7 @@ describe("buildCommand output config", () => {
942960
TestContext
943961
>({
944962
docs: { brief: "Test" },
963+
auth: false,
945964
output: { human: () => "unused" },
946965
parameters: {
947966
flags: {
@@ -996,6 +1015,7 @@ describe("buildCommand return-based output", () => {
9961015
TestContext
9971016
>({
9981017
docs: { brief: "Test" },
1018+
auth: false,
9991019
output: {
10001020
human: (d: { name: string; role: string }) => `${d.name} (${d.role})`,
10011021
},
@@ -1024,6 +1044,7 @@ describe("buildCommand return-based output", () => {
10241044
TestContext
10251045
>({
10261046
docs: { brief: "Test" },
1047+
auth: false,
10271048
output: {
10281049
human: (d: { name: string; role: string }) => `${d.name} (${d.role})`,
10291050
},
@@ -1053,6 +1074,7 @@ describe("buildCommand return-based output", () => {
10531074
TestContext
10541075
>({
10551076
docs: { brief: "Test" },
1077+
auth: false,
10561078
output: {
10571079
human: (d: { id: number; name: string; role: string }) => `${d.name}`,
10581080
},
@@ -1084,6 +1106,7 @@ describe("buildCommand return-based output", () => {
10841106
const makeCommand = () =>
10851107
buildCommand<{ json: boolean; fields?: string[] }, [], TestContext>({
10861108
docs: { brief: "Test" },
1109+
auth: false,
10871110
output: {
10881111
human: (d: { value: number }) => `Value: ${d.value}`,
10891112
},
@@ -1131,6 +1154,7 @@ describe("buildCommand return-based output", () => {
11311154
TestContext
11321155
>({
11331156
docs: { brief: "Test" },
1157+
auth: false,
11341158
output: {
11351159
human: () => "unused",
11361160
},
@@ -1188,6 +1212,7 @@ describe("buildCommand return-based output", () => {
11881212
TestContext
11891213
>({
11901214
docs: { brief: "Test" },
1215+
auth: false,
11911216
output: {
11921217
human: (d: { name: string }) => `Hello, ${d.name}!`,
11931218
},
@@ -1218,6 +1243,7 @@ describe("buildCommand return-based output", () => {
12181243
TestContext
12191244
>({
12201245
docs: { brief: "Test" },
1246+
auth: false,
12211247
output: {
12221248
human: (d: Array<{ id: number }>) => d.map(((x) => x.id).join(", ")),
12231249
},
@@ -1247,6 +1273,7 @@ describe("buildCommand return-based output", () => {
12471273
const makeCommand = () =>
12481274
buildCommand<{ json: boolean; fields?: string[] }, [], TestContext>({
12491275
docs: { brief: "Test" },
1276+
auth: false,
12501277
output: {
12511278
human: (d: { org: string }) => `Org: ${d.org}`,
12521279
},
@@ -1285,6 +1312,7 @@ describe("buildCommand return-based output", () => {
12851312
TestContext
12861313
>({
12871314
docs: { brief: "Test" },
1315+
auth: false,
12881316
output: {
12891317
human: (d: { error: string }) => `Error: ${d.error}`,
12901318
},
@@ -1333,6 +1361,7 @@ describe("buildCommand return-based output", () => {
13331361
TestContext
13341362
>({
13351363
docs: { brief: "Test" },
1364+
auth: false,
13361365
output: {
13371366
human: (d: { error: string }) => `Error: ${d.error}`,
13381367
},

test/preload.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ delete process.env.SENTRY_HOST;
9393
delete process.env.SENTRY_ORG;
9494
delete process.env.SENTRY_PROJECT;
9595

96+
// Set a fake auth token so buildCommand's auth guard passes in tests.
97+
// Real API calls are blocked by the global fetch mock below.
98+
// Tests that specifically verify unauthenticated behavior (e.g., auth status)
99+
// mock getAuthConfig to return undefined.
100+
process.env.SENTRY_AUTH_TOKEN = "sntrys_test-token-for-unit-tests_000000";
101+
96102
// Disable telemetry and background update checks in tests
97103
// This prevents Sentry SDK from keeping the process alive and making external calls
98104
process.env.SENTRY_CLI_NO_TELEMETRY = "1";

0 commit comments

Comments
 (0)