Skip to content

Commit

Permalink
feat(clerk-js): Sign Out from multiple tabs at once (#2094)
Browse files Browse the repository at this point in the history
* feat(clerk-js): Enable BroadcastChannel

* chore(clerk-js): Remove object passed as it is the default value of the parameter

* chore(repo): Add Clerk types in integrations tests

* test(repo): Add tests for Sign Out functionality

* chore(repo): Adds Changeset

* fix(repo): Import expect form @playwright/test

* test(repo): Check if user is signed out
  • Loading branch information
octoper authored Nov 13, 2023
1 parent 4509da5 commit 08dd88c
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/dry-sheep-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': minor
---

Introducing sign out from all open tabs at once.
1 change: 0 additions & 1 deletion integration/testUtils/appPageObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const createAppPageObject = (testArgs: { page: Page }, app: Application)
},
waitForClerkJsLoaded: async () => {
return page.waitForFunction(() => {
// @ts-ignore
return window.Clerk?.isReady();
});
},
Expand Down
2 changes: 0 additions & 2 deletions integration/testUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ const createExpectPageObject = ({ page }: TestArgs) => {
return {
toBeSignedOut: () => {
return page.waitForFunction(() => {
// @ts-ignore
return !window.Clerk?.user;
});
},
toBeSignedIn: async () => {
return page.waitForFunction(() => {
// @ts-ignore
return !!window.Clerk?.user;
});
},
Expand Down
48 changes: 48 additions & 0 deletions integration/tests/sign-out-smoke.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect, test } from '@playwright/test';

import { appConfigs } from '../presets';
import type { FakeUser } from '../testUtils';
import { createTestUtils, testAgainstRunningApps } from '../testUtils';

testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign out smoke test @generic', ({ app }) => {
test.describe.configure({ mode: 'serial' });

let fakeUser: FakeUser;

test.beforeAll(async () => {
const u = createTestUtils({ app });
fakeUser = u.services.users.createFakeUser();
await u.services.users.createBapiUser(fakeUser);
});

test.afterAll(async () => {
await fakeUser.deleteIfExists();
await app.teardown();
});

test('sign out throught all open tabs at once', async ({ page, context }) => {
const mainTab = createTestUtils({ app, page, context });
await mainTab.po.signIn.goTo();
await mainTab.po.signIn.setIdentifier(fakeUser.email);
await mainTab.po.signIn.continue();
await mainTab.po.signIn.setPassword(fakeUser.password);
await mainTab.po.signIn.continue();
await mainTab.po.expect.toBeSignedIn();

await mainTab.tabs.runInNewTab(async m => {
await m.page.goToStart();

await m.page.waitForClerkJsLoaded();

await m.po.expect.toBeSignedIn();

await m.page.evaluate(async () => {
await window.Clerk.signOut();
});

await m.po.expect.toBeSignedOut();
});

expect(await mainTab.page.evaluate('!window.Clerk.user')).toBe(false);
});
});
2 changes: 1 addition & 1 deletion integration/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"include": ["./tests"],
"include": ["./tests", "types.d.ts"],
"exclude": ["templates"]
}
7 changes: 7 additions & 0 deletions integration/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Clerk } from '@clerk/types';

declare global {
interface Window {
Clerk: Clerk;
}
}
5 changes: 3 additions & 2 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { LocalStorageBroadcastChannel } from '@clerk/shared';
import {
addClerkPrefix,
handleValueOrFn,
Expand All @@ -7,6 +6,7 @@ import {
isHttpOrHttps,
isValidBrowserOnline,
isValidProxyUrl,
LocalStorageBroadcastChannel,
noop,
parsePublishableKey,
proxyUrlToAbsoluteURL,
Expand Down Expand Up @@ -1282,6 +1282,7 @@ export default class Clerk implements ClerkInterface {

const isInAccountsHostedPages = isDevAccountPortalOrigin(window?.location.hostname);

this.#broadcastChannel = new LocalStorageBroadcastChannel('clerk');
this.#setupListeners();

let retries = 0;
Expand Down Expand Up @@ -1375,7 +1376,7 @@ export default class Clerk implements ClerkInterface {

this.#broadcastChannel?.addEventListener('message', ({ data }) => {
if (data.type === 'signout') {
void this.handleUnauthenticated({ broadcast: false });
void this.handleUnauthenticated();
}
});
};
Expand Down

0 comments on commit 08dd88c

Please sign in to comment.