Skip to content

Commit 08f0124

Browse files
committed
fix(settings): uses openGitHubUrl wrapper, adds syncing test
1 parent 2ac948b commit 08f0124

File tree

2 files changed

+27
-12
lines changed

2 files changed

+27
-12
lines changed

src/app/components/settings/SettingsPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { config, updateConfig } from "../../stores/config";
44
import { clearAuth } from "../../stores/auth";
55
import { clearCache } from "../../stores/cache";
66
import { buildOrgAccessUrl } from "../../lib/oauth";
7+
import { openGitHubUrl } from "../../lib/url";
78
import { fetchOrgs } from "../../services/api";
89
import { getClient } from "../../services/github";
910
import OrgSelector from "../onboarding/OrgSelector";
@@ -227,7 +228,7 @@ export default function SettingsPage() {
227228
}
228229

229230
function handleGrantOrgs() {
230-
window.open(buildOrgAccessUrl(), "_blank", "noopener");
231+
openGitHubUrl(buildOrgAccessUrl());
231232
// Remove any prior focus listener before adding a new one (dedup on rapid clicks)
232233
if (pendingFocusHandler) {
233234
window.removeEventListener("focus", pendingFocusHandler);

tests/components/settings/SettingsPage.test.tsx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ vi.mock("../../../src/app/services/api", () => ({
4141
fetchRepos: vi.fn().mockResolvedValue([]),
4242
}));
4343

44+
vi.mock("../../../src/app/lib/url", () => ({
45+
openGitHubUrl: vi.fn(),
46+
}));
47+
4448
// ── Imports after mocks ───────────────────────────────────────────────────────
4549

4650
import { render } from "@solidjs/testing-library";
@@ -51,6 +55,7 @@ import * as cacheStore from "../../../src/app/stores/cache";
5155
import * as apiModule from "../../../src/app/services/api";
5256
import { updateConfig, config } from "../../../src/app/stores/config";
5357
import { buildOrgAccessUrl } from "../../../src/app/lib/oauth";
58+
import * as urlModule from "../../../src/app/lib/url";
5459

5560
// ── Helpers ───────────────────────────────────────────────────────────────────
5661

@@ -526,25 +531,19 @@ describe("SettingsPage — Grant more orgs button", () => {
526531
screen.getByRole("button", { name: "Grant more orgs" });
527532
});
528533

529-
it("clicking 'Grant more orgs' opens GitHub app settings in new tab", async () => {
534+
it("clicking 'Grant more orgs' opens GitHub app settings via openGitHubUrl", async () => {
530535
const user = userEvent.setup();
531536
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
532-
const openSpy = vi.spyOn(window, "open").mockImplementation(() => null);
533537
renderSettings();
534538
const btn = screen.getByRole("button", { name: "Grant more orgs" });
535539
await user.click(btn);
536-
expect(openSpy).toHaveBeenCalledWith(
537-
buildOrgAccessUrl(),
538-
"_blank",
539-
"noopener",
540-
);
540+
expect(urlModule.openGitHubUrl).toHaveBeenCalledWith(buildOrgAccessUrl());
541541
vi.unstubAllEnvs();
542542
});
543543

544544
it("clicking 'Grant more orgs' registers a focus listener for auto-merge", async () => {
545545
const user = userEvent.setup();
546546
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
547-
vi.spyOn(window, "open").mockImplementation(() => null);
548547
const addSpy = vi.spyOn(window, "addEventListener");
549548
renderSettings();
550549
const btn = screen.getByRole("button", { name: "Grant more orgs" });
@@ -553,10 +552,27 @@ describe("SettingsPage — Grant more orgs button", () => {
553552
vi.unstubAllEnvs();
554553
});
555554

555+
it("shows 'Syncing...' on button while merging and reverts after", async () => {
556+
const user = userEvent.setup();
557+
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
558+
updateConfig({ selectedOrgs: [] });
559+
vi.mocked(apiModule.fetchOrgs).mockResolvedValue([]);
560+
renderSettings();
561+
const btn = screen.getByRole("button", { name: "Grant more orgs" });
562+
await user.click(btn);
563+
window.dispatchEvent(new Event("focus"));
564+
await waitFor(() => {
565+
expect(screen.getByRole("button", { name: "Syncing..." })).toBeDefined();
566+
});
567+
await waitFor(() => {
568+
expect(screen.getByRole("button", { name: "Grant more orgs" })).toBeDefined();
569+
});
570+
vi.unstubAllEnvs();
571+
});
572+
556573
it("auto-merges new orgs when window regains focus after granting", async () => {
557574
const user = userEvent.setup();
558575
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
559-
vi.spyOn(window, "open").mockImplementation(() => null);
560576
updateConfig({ selectedOrgs: ["existing-org"] });
561577
vi.mocked(apiModule.fetchOrgs).mockResolvedValue([
562578
{ login: "existing-org", avatarUrl: "", type: "org" },
@@ -580,7 +596,6 @@ describe("SettingsPage — Grant more orgs button", () => {
580596
it("silently handles fetchOrgs rejection on focus without breaking", async () => {
581597
const user = userEvent.setup();
582598
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
583-
vi.spyOn(window, "open").mockImplementation(() => null);
584599
updateConfig({ selectedOrgs: ["existing-org"] });
585600
vi.mocked(apiModule.fetchOrgs).mockRejectedValue(new Error("Network error"));
586601
renderSettings();
@@ -597,7 +612,6 @@ describe("SettingsPage — Grant more orgs button", () => {
597612
it("skips merge on focus when getClient returns null", async () => {
598613
const user = userEvent.setup();
599614
vi.stubEnv("VITE_GITHUB_CLIENT_ID", "test-client-id");
600-
vi.spyOn(window, "open").mockImplementation(() => null);
601615
const github = await import("../../../src/app/services/github");
602616
vi.mocked(github.getClient).mockReturnValue(null);
603617
renderSettings();

0 commit comments

Comments
 (0)