Skip to content

Commit 9aee126

Browse files
betegonclaude
andcommitted
test(auth): add unit tests for rcTokenHint host-matching logic
Covers the five branches that were implicated in review bugs: no token, SaaS match, self-hosted rc URL match, rc URL mismatch, and bare SaaS token against a self-hosted host. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 472df59 commit 9aee126

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

src/commands/auth/login.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ async function resolveRcContext(
181181
* no URL is set in the rc file (global SaaS token) or the rc URL matches
182182
* effectiveHost. A mismatched URL means the token is for a different instance.
183183
*/
184-
function rcTokenHint(
184+
/** @internal exported for testing */
185+
export function rcTokenHint(
185186
rcConfig: SentryCliRcConfig,
186187
effectiveHost: string
187188
): string | undefined {

test/commands/auth/login.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ mock.module("../../../src/lib/logger.js", () => ({
7979
// Dynamic import: must run AFTER mock.module() so login.ts picks up fakeLog.
8080
const { loginCommand } = await import("../../../src/commands/auth/login.js");
8181

82+
import { rcTokenHint } from "../../../src/commands/auth/login.js";
8283
// biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
8384
import * as apiClient from "../../../src/lib/api-client.js";
8485
// biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
@@ -88,6 +89,7 @@ import * as dbUser from "../../../src/lib/db/user.js";
8889
import { AuthError } from "../../../src/lib/errors.js";
8990
// biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
9091
import * as interactiveLogin from "../../../src/lib/interactive-login.js";
92+
import type { SentryCliRcConfig } from "../../../src/lib/sentryclirc.js";
9193

9294
type LoginFlags = {
9395
readonly token?: string;
@@ -780,3 +782,52 @@ describe("applyLoginUrl (trust anchor registration)", () => {
780782
).toBe(false);
781783
});
782784
});
785+
786+
function makeRcConfig(
787+
token: string | undefined,
788+
url?: string
789+
): SentryCliRcConfig {
790+
return {
791+
token,
792+
url,
793+
sources: { token: token ? "~/.sentryclirc" : undefined },
794+
};
795+
}
796+
797+
describe("rcTokenHint", () => {
798+
test("no token → no hint", () => {
799+
expect(
800+
rcTokenHint(makeRcConfig(undefined), "https://sentry.io")
801+
).toBeUndefined();
802+
});
803+
804+
test("SaaS host, no rc URL → hint without --url", () => {
805+
const hint = rcTokenHint(makeRcConfig("sntrys_abc"), "https://sentry.io");
806+
expect(hint).toContain("sentry auth login --token <token>");
807+
expect(hint).not.toContain("--url");
808+
});
809+
810+
test("self-hosted, rc URL matches → hint includes --url", () => {
811+
const hint = rcTokenHint(
812+
makeRcConfig("sntrys_abc", "https://self.example.com"),
813+
"https://self.example.com"
814+
);
815+
expect(hint).toContain("--url https://self.example.com");
816+
});
817+
818+
test("self-hosted, rc URL mismatches → no hint (token is for a different instance)", () => {
819+
const hint = rcTokenHint(
820+
makeRcConfig("sntrys_abc", "https://other.example.com"),
821+
"https://self.example.com"
822+
);
823+
expect(hint).toBeUndefined();
824+
});
825+
826+
test("self-hosted, no rc URL → no hint (bare SaaS token shouldn't be suggested for self-hosted)", () => {
827+
const hint = rcTokenHint(
828+
makeRcConfig("sntrys_abc"),
829+
"https://self.example.com"
830+
);
831+
expect(hint).toBeUndefined();
832+
});
833+
});

0 commit comments

Comments
 (0)