Skip to content

Commit 38c3fad

Browse files
fix(twitch): export clearRegistryForTest for cross-test isolation (#83887)
Co-authored-by: hcl <7755017+hclsys@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
1 parent 6f7cf7d commit 38c3fad

2 files changed

Lines changed: 16 additions & 9 deletions

File tree

extensions/twitch/src/client-manager-registry.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@ function makeLogger(): ChannelLogSink {
1616
}
1717

1818
describe("client manager registry", () => {
19-
afterEach(() => {
20-
clearRegistryForTest();
19+
afterEach(async () => {
20+
await clearRegistryForTest();
2121
});
2222

23-
it("clears cached managers for hot module test isolation", () => {
23+
it("clears cached managers for hot module test isolation", async () => {
2424
const firstManager = getOrCreateClientManager("default", makeLogger());
25+
const disconnectAll = vi.spyOn(firstManager, "disconnectAll");
2526

2627
expect(getClientManager("default")).toBe(firstManager);
2728
expect(getOrCreateClientManager("default", makeLogger())).toBe(firstManager);
2829

29-
clearRegistryForTest();
30+
await clearRegistryForTest();
3031

32+
expect(disconnectAll).toHaveBeenCalledOnce();
3133
expect(getClientManager("default")).toBeUndefined();
3234
expect(getOrCreateClientManager("default", makeLogger())).not.toBe(firstManager);
3335
});

extensions/twitch/src/client-manager-registry.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,17 @@ export async function removeClientManager(accountId: string): Promise<void> {
9393
* this, the module-level `registry` Map survives across tests when vitest
9494
* is run with `--isolate=false` (or any harness that does not tear the
9595
* module graph down between cases), and a stale entry from one test will
96-
* shadow `getOrCreateClientManager` calls in subsequent tests silently
96+
* shadow `getOrCreateClientManager` calls in subsequent tests, silently
9797
* handing back another test's mocked logger/manager. See #83887.
9898
*
99-
* Production code MUST NOT call this. It is safe to call when the registry
100-
* is empty (clear() is a no-op on an empty Map).
99+
* Production code MUST NOT call this. It disconnects cached managers before
100+
* clearing the registry so tests do not leave handlers or clients behind.
101101
*/
102-
export function clearRegistryForTest(): void {
103-
registry.clear();
102+
export async function clearRegistryForTest(): Promise<void> {
103+
const entries = [...registry.values()];
104+
try {
105+
await Promise.all(entries.map((entry) => entry.manager.disconnectAll()));
106+
} finally {
107+
registry.clear();
108+
}
104109
}

0 commit comments

Comments
 (0)