Skip to content

Commit b8b64e4

Browse files
feat: include force_all_guides param on socket connection when in debug mode (#723)
### Description Include force_all_guides param on Guides socket channel. Resubscribes when exiting/entering debug mode. ### Checklist - [x] Tests have been added for new features or major refactors to existing features.
1 parent 47fb18f commit b8b64e4

File tree

3 files changed

+132
-5
lines changed

3 files changed

+132
-5
lines changed

.changeset/proud-donkeys-mate.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@knocklabs/react-core": minor
3+
"@knocklabs/client": minor
4+
"@knocklabs/react": minor
5+
---
6+
7+
feat(beta): add support for basic guide debugging

packages/client/src/clients/guide/client.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,13 @@ export class KnockGuideClient {
341341
}
342342

343343
// Join the channel topic and subscribe to supported events.
344-
const params = { ...this.targetParams, user_id: this.knock.userId };
344+
const debugState = this.store.state.debug;
345+
const params = {
346+
...this.targetParams,
347+
user_id: this.knock.userId,
348+
force_all_guides: debugState.forcedGuideKey ? true : undefined,
349+
};
350+
345351
const newChannel = this.socket.channel(this.socketChannelTopic, params);
346352

347353
for (const eventType of this.socketEventTypes) {
@@ -978,16 +984,22 @@ export class KnockGuideClient {
978984

979985
this.knock.log(`[Guide] Handle Location change: ${href}`);
980986

987+
// If entering debug mode, fetch all guides.
988+
const currentDebugParams = this.store.state.debug;
981989
const newDebugParams = detectDebugParams();
982990
this.setLocation(href, { debug: newDebugParams });
983991

984-
// If entering debug mode, fetch all guides.
985-
const currentDebugParams = this.store.state.debug;
986-
if (!currentDebugParams.forcedGuideKey && !!newDebugParams.forcedGuideKey) {
992+
// If entering/exiting debug mode, refetch guides and resubscribe to the
993+
// websocket channel.
994+
if (
995+
Boolean(currentDebugParams.forcedGuideKey) !==
996+
Boolean(newDebugParams.forcedGuideKey)
997+
) {
987998
this.knock.log(
988-
`[Guide] Entering debug mode for key: ${newDebugParams.forcedGuideKey}`,
999+
`[Guide] ${newDebugParams.forcedGuideKey ? "Entering" : "Exiting"} debug mode`,
9891000
);
9901001
this.fetch();
1002+
this.subscribe();
9911003
}
9921004
};
9931005

packages/client/test/clients/guide/guide.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,52 @@ describe("KnockGuideClient", () => {
450450
expect(mockChannel.off).toHaveBeenCalled();
451451
expect(mockChannel.leave).toHaveBeenCalled();
452452
});
453+
454+
test("subscribe includes force_all_guides when debug state has forcedGuideKey", () => {
455+
const mockChannel = {
456+
join: vi.fn().mockReturnValue({
457+
receive: vi.fn().mockReturnValue({
458+
receive: vi.fn().mockReturnValue({
459+
receive: vi.fn(),
460+
}),
461+
}),
462+
}),
463+
on: vi.fn(),
464+
off: vi.fn(),
465+
leave: vi.fn(),
466+
state: "closed",
467+
};
468+
469+
const mockSocket = {
470+
channel: vi.fn().mockReturnValue(mockChannel),
471+
isConnected: vi.fn().mockReturnValue(true),
472+
connect: vi.fn(),
473+
};
474+
475+
mockApiClient.socket = mockSocket as unknown as Socket;
476+
vi.mocked(mockKnock.client).mockReturnValue(mockApiClient as ApiClient);
477+
478+
const client = new KnockGuideClient(
479+
mockKnock,
480+
channelId,
481+
defaultTargetParams,
482+
);
483+
484+
// Set debug state with forced guide key
485+
client.store.state.debug = { forcedGuideKey: "test_guide" };
486+
487+
client.subscribe();
488+
489+
expect(mockSocket.channel).toHaveBeenCalledWith(
490+
`guides:${channelId}`,
491+
expect.objectContaining({
492+
user_id: mockKnock.userId,
493+
data: defaultTargetParams.data,
494+
tenant: defaultTargetParams.tenant,
495+
force_all_guides: true,
496+
}),
497+
);
498+
});
453499
});
454500

455501
describe("guide operations", () => {
@@ -1904,6 +1950,68 @@ describe("KnockGuideClient", () => {
19041950
expect(windowWithHistory.history.pushState).toBe(originalPushState);
19051951
expect(windowWithHistory.history.replaceState).toBe(originalReplaceState);
19061952
});
1953+
1954+
test("handleLocationChange calls subscribe when entering debug mode", () => {
1955+
vi.stubGlobal("window", {
1956+
...mockWindow,
1957+
location: {
1958+
href: "https://example.com/dashboard?knock_guide_key=test_guide",
1959+
search: "?knock_guide_key=test_guide",
1960+
},
1961+
});
1962+
1963+
const client = new KnockGuideClient(
1964+
mockKnock,
1965+
channelId,
1966+
{},
1967+
{ trackLocationFromWindow: true },
1968+
);
1969+
1970+
client.store.state.debug = { forcedGuideKey: null };
1971+
client.store.state.location = "https://example.com/dashboard";
1972+
1973+
const subscribeSpy = vi
1974+
.spyOn(client, "subscribe")
1975+
.mockImplementation(() => {});
1976+
1977+
const fetchSpy = vi
1978+
.spyOn(client, "fetch")
1979+
.mockImplementation(() => Promise.resolve({ status: "ok" }));
1980+
1981+
client["handleLocationChange"]();
1982+
1983+
expect(fetchSpy).toHaveBeenCalled();
1984+
expect(subscribeSpy).toHaveBeenCalled();
1985+
});
1986+
1987+
test("handleLocationChange calls subscribe when exiting debug mode", () => {
1988+
vi.stubGlobal("window", {
1989+
...mockWindow,
1990+
location: {
1991+
href: "https://example.com/dashboard",
1992+
search: "",
1993+
},
1994+
});
1995+
1996+
const client = new KnockGuideClient(
1997+
mockKnock,
1998+
channelId,
1999+
{},
2000+
{ trackLocationFromWindow: true },
2001+
);
2002+
2003+
client.store.state.debug = { forcedGuideKey: "test_guide" };
2004+
client.store.state.location =
2005+
"https://example.com/dashboard?knock_guide_key=test_guide";
2006+
2007+
const subscribeSpy = vi
2008+
.spyOn(client, "subscribe")
2009+
.mockImplementation(() => {});
2010+
2011+
client["handleLocationChange"]();
2012+
2013+
expect(subscribeSpy).toHaveBeenCalled();
2014+
});
19072015
});
19082016

19092017
describe("private methods", () => {

0 commit comments

Comments
 (0)