Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions test/commands/auth/logout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ describe("logoutCommand.func", () => {
isAuthenticatedSpy.mockReturnValue(true);
isEnvTokenActiveSpy.mockReturnValue(true);
// Set env var directly — getActiveEnvVarName() reads env vars via getEnvToken()
// Clear SENTRY_AUTH_TOKEN so SENTRY_TOKEN takes priority
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
delete process.env.SENTRY_AUTH_TOKEN;
process.env.SENTRY_TOKEN = "sntrys_token_456";
const { context } = createContext();

Expand All @@ -138,6 +141,9 @@ describe("logoutCommand.func", () => {
expect(msg).toContain("SENTRY_TOKEN");
} finally {
delete process.env.SENTRY_TOKEN;
if (savedAuthToken !== undefined) {
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
}
}
expect(clearAuthSpy).not.toHaveBeenCalled();
});
Expand Down
6 changes: 6 additions & 0 deletions test/commands/auth/refresh.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ describe("refreshCommand.func", () => {
test("env token (SENTRY_TOKEN): throws AuthError with SENTRY_TOKEN in message", async () => {
isEnvTokenActiveSpy.mockReturnValue(true);
// Set env var directly — getActiveEnvVarName() reads env vars via getEnvToken()
// Clear SENTRY_AUTH_TOKEN so SENTRY_TOKEN takes priority
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
delete process.env.SENTRY_AUTH_TOKEN;
process.env.SENTRY_TOKEN = "sntrys_token_456";

const { context } = createContext();
Expand All @@ -99,6 +102,9 @@ describe("refreshCommand.func", () => {
expect((err as AuthError).message).not.toContain("SENTRY_AUTH_TOKEN");
} finally {
delete process.env.SENTRY_TOKEN;
if (savedAuthToken !== undefined) {
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
}
}

expect(refreshTokenSpy).not.toHaveBeenCalled();
Expand Down
20 changes: 20 additions & 0 deletions test/commands/auth/whoami.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ describe("whoamiCommand.func", () => {
});

describe("unauthenticated", () => {
let getAuthConfigSpy: ReturnType<typeof spyOn>;
let savedAuthToken: string | undefined;

beforeEach(() => {
// Clear env token and mock getAuthConfig so buildCommand's auth guard
// sees no credentials — this tests the unauthenticated path end-to-end.
savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
delete process.env.SENTRY_AUTH_TOKEN;
getAuthConfigSpy = spyOn(dbAuth, "getAuthConfig").mockReturnValue(
undefined
);
});

afterEach(() => {
getAuthConfigSpy.mockRestore();
if (savedAuthToken !== undefined) {
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
}
});

test("throws AuthError(not_authenticated) when no token stored", async () => {
isAuthenticatedSpy.mockReturnValue(false);

Expand Down
38 changes: 28 additions & 10 deletions test/commands/project/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -969,8 +969,17 @@ describe("fetchOrgProjectsSafe", () => {
test("propagates AuthError when not authenticated", async () => {
// Clear auth token so the API client throws AuthError before making any request
await clearAuth();

await expect(fetchOrgProjectsSafe("myorg")).rejects.toThrow(AuthError);
// Also clear env token — preload sets a fake one for the auth guard
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
delete process.env.SENTRY_AUTH_TOKEN;

try {
await expect(fetchOrgProjectsSafe("myorg")).rejects.toThrow(AuthError);
} finally {
if (savedAuthToken !== undefined) {
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
}
}
});
});

Expand Down Expand Up @@ -1233,14 +1242,23 @@ describe("handleAutoDetect", () => {
setDefaults("test-org");
// Clear auth so getAuthToken() throws AuthError before any fetch
await clearAuth();

await expect(
handleAutoDetect("/tmp/test-project", {
limit: 30,
json: true,
fresh: false,
})
).rejects.toThrow(AuthError);
// Also clear env token — preload sets a fake one for the auth guard
const savedAuthToken = process.env.SENTRY_AUTH_TOKEN;
delete process.env.SENTRY_AUTH_TOKEN;

try {
await expect(
handleAutoDetect("/tmp/test-project", {
limit: 30,
json: true,
fresh: false,
})
).rejects.toThrow(AuthError);
} finally {
if (savedAuthToken !== undefined) {
process.env.SENTRY_AUTH_TOKEN = savedAuthToken;
}
}
});

test("slow path: uses full fetch when platform filter is active", async () => {
Expand Down
29 changes: 29 additions & 0 deletions test/lib/command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ describe("buildCommand", () => {
test("builds a valid command object", () => {
const command = buildCommand({
docs: { brief: "Test command" },
auth: false,
parameters: {
flags: {
verbose: { kind: "boolean", brief: "Verbose", default: false },
Expand All @@ -91,6 +92,7 @@ describe("buildCommand", () => {
test("handles commands with empty parameters", () => {
const command = buildCommand({
docs: { brief: "Simple command" },
auth: false,
parameters: {},
async *func() {
// no-op
Expand Down Expand Up @@ -128,6 +130,7 @@ describe("buildCommand telemetry integration", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
verbose: { kind: "boolean", brief: "Verbose", default: false },
Expand Down Expand Up @@ -168,6 +171,7 @@ describe("buildCommand telemetry integration", () => {
test("skips false boolean flags in telemetry", async () => {
const command = buildCommand<{ json: boolean }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
json: { kind: "boolean", brief: "JSON output", default: false },
Expand Down Expand Up @@ -199,6 +203,7 @@ describe("buildCommand telemetry integration", () => {

const command = buildCommand<Record<string, never>, [string], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
positional: {
kind: "tuple",
Expand Down Expand Up @@ -236,6 +241,7 @@ describe("buildCommand telemetry integration", () => {

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

const command = buildCommand<{ delay: number }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
delay: {
Expand Down Expand Up @@ -371,6 +378,7 @@ describe("buildCommand", () => {
test("builds a valid command object", () => {
const command = buildCommand({
docs: { brief: "Test command" },
auth: false,
parameters: {
flags: {
json: { kind: "boolean", brief: "JSON output", default: false },
Expand All @@ -388,6 +396,7 @@ describe("buildCommand", () => {

const command = buildCommand<{ json: boolean }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
json: { kind: "boolean", brief: "JSON output", default: false },
Expand Down Expand Up @@ -499,6 +508,7 @@ describe("buildCommand", () => {

const command = buildCommand<{ limit: number }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
limit: {
Expand Down Expand Up @@ -547,6 +557,7 @@ describe("buildCommand", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
verbose: {
Expand Down Expand Up @@ -603,6 +614,7 @@ describe("buildCommand", () => {
try {
const command = buildCommand<{ verbose: boolean }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
parameters: {
flags: {
verbose: {
Expand Down Expand Up @@ -674,6 +686,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {
flags: {
Expand Down Expand Up @@ -717,6 +730,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {},
// biome-ignore lint/correctness/useYield: test command — no output to yield
Expand Down Expand Up @@ -756,6 +770,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {},
// biome-ignore lint/correctness/useYield: test command — no output to yield
Expand Down Expand Up @@ -794,6 +809,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {},
// biome-ignore lint/correctness/useYield: test command — no output to yield
Expand Down Expand Up @@ -858,6 +874,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {
flags: {
Expand Down Expand Up @@ -901,6 +918,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {},
// biome-ignore lint/correctness/useYield: test command — no output to yield
Expand Down Expand Up @@ -942,6 +960,7 @@ describe("buildCommand output config", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: { human: () => "unused" },
parameters: {
flags: {
Expand Down Expand Up @@ -996,6 +1015,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { name: string; role: string }) => `${d.name} (${d.role})`,
},
Expand Down Expand Up @@ -1024,6 +1044,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { name: string; role: string }) => `${d.name} (${d.role})`,
},
Expand Down Expand Up @@ -1053,6 +1074,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { id: number; name: string; role: string }) => `${d.name}`,
},
Expand Down Expand Up @@ -1084,6 +1106,7 @@ describe("buildCommand return-based output", () => {
const makeCommand = () =>
buildCommand<{ json: boolean; fields?: string[] }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { value: number }) => `Value: ${d.value}`,
},
Expand Down Expand Up @@ -1131,6 +1154,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: () => "unused",
},
Expand Down Expand Up @@ -1188,6 +1212,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { name: string }) => `Hello, ${d.name}!`,
},
Expand Down Expand Up @@ -1218,6 +1243,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: Array<{ id: number }>) => d.map(((x) => x.id).join(", ")),
},
Expand Down Expand Up @@ -1247,6 +1273,7 @@ describe("buildCommand return-based output", () => {
const makeCommand = () =>
buildCommand<{ json: boolean; fields?: string[] }, [], TestContext>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { org: string }) => `Org: ${d.org}`,
},
Expand Down Expand Up @@ -1285,6 +1312,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { error: string }) => `Error: ${d.error}`,
},
Expand Down Expand Up @@ -1333,6 +1361,7 @@ describe("buildCommand return-based output", () => {
TestContext
>({
docs: { brief: "Test" },
auth: false,
output: {
human: (d: { error: string }) => `Error: ${d.error}`,
},
Expand Down
6 changes: 6 additions & 0 deletions test/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ delete process.env.SENTRY_HOST;
delete process.env.SENTRY_ORG;
delete process.env.SENTRY_PROJECT;

// Set a fake auth token so buildCommand's auth guard passes in tests.
// Real API calls are blocked by the global fetch mock below.
// Tests that specifically verify unauthenticated behavior (e.g., auth status)
// mock getAuthConfig to return undefined.
process.env.SENTRY_AUTH_TOKEN = "sntrys_test-token-for-unit-tests_000000";

// Disable telemetry and background update checks in tests
// This prevents Sentry SDK from keeping the process alive and making external calls
process.env.SENTRY_CLI_NO_TELEMETRY = "1";
Expand Down
Loading