From 83c7ab8be071d8e40b9d20d4e053529782642c17 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Thu, 9 Nov 2023 13:12:32 +0200 Subject: [PATCH 1/7] feat(clerk-js): Enable BroadcastChannel --- packages/clerk-js/src/core/clerk.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index da64be8148c..7fadb8829c7 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1,4 +1,3 @@ -import type { LocalStorageBroadcastChannel } from '@clerk/shared'; import { addClerkPrefix, handleValueOrFn, @@ -7,6 +6,7 @@ import { isHttpOrHttps, isValidBrowserOnline, isValidProxyUrl, + LocalStorageBroadcastChannel, noop, parsePublishableKey, proxyUrlToAbsoluteURL, @@ -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; @@ -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({ broadcast: true }); } }); }; From ecfed064d9abcec8c0c05821e6821f453d1a2fb0 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Thu, 9 Nov 2023 17:48:58 +0200 Subject: [PATCH 2/7] chore(clerk-js): Remove object passed as it is the default value of the parameter --- packages/clerk-js/src/core/clerk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts index 7fadb8829c7..e9d462b8677 100644 --- a/packages/clerk-js/src/core/clerk.ts +++ b/packages/clerk-js/src/core/clerk.ts @@ -1376,7 +1376,7 @@ export default class Clerk implements ClerkInterface { this.#broadcastChannel?.addEventListener('message', ({ data }) => { if (data.type === 'signout') { - void this.handleUnauthenticated({ broadcast: true }); + void this.handleUnauthenticated(); } }); }; From 8d2d54ce7e47ce18ce55750242fa43ff6495d7cf Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Thu, 9 Nov 2023 17:54:10 +0200 Subject: [PATCH 3/7] chore(repo): Add Clerk types in integrations tests --- integration/testUtils/appPageObject.ts | 1 - integration/tsconfig.json | 2 +- integration/types.d.ts | 7 +++++++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 integration/types.d.ts diff --git a/integration/testUtils/appPageObject.ts b/integration/testUtils/appPageObject.ts index 0a8cb4614da..f5063cbe577 100644 --- a/integration/testUtils/appPageObject.ts +++ b/integration/testUtils/appPageObject.ts @@ -31,7 +31,6 @@ export const createAppPageObject = (testArgs: { page: Page }, app: Application) }, waitForClerkJsLoaded: async () => { return page.waitForFunction(() => { - // @ts-ignore return window.Clerk?.isReady(); }); }, diff --git a/integration/tsconfig.json b/integration/tsconfig.json index 4361874219f..441382fe67b 100644 --- a/integration/tsconfig.json +++ b/integration/tsconfig.json @@ -6,6 +6,6 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true }, - "include": ["./tests"], + "include": ["./tests", "types.d.ts"], "exclude": ["templates"] } diff --git a/integration/types.d.ts b/integration/types.d.ts new file mode 100644 index 00000000000..8df81fba45b --- /dev/null +++ b/integration/types.d.ts @@ -0,0 +1,7 @@ +import type { Clerk } from '@clerk/types'; + +declare global { + interface Window { + Clerk: Clerk; + } +} From 7b6afaba25e5ea6ef55a4c89b74dcf483f5fd2a0 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Thu, 9 Nov 2023 17:55:50 +0200 Subject: [PATCH 4/7] test(repo): Add tests for Sign Out functionality --- integration/testUtils/index.ts | 2 -- integration/tests/sign-out-smoke.test.ts | 46 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 integration/tests/sign-out-smoke.test.ts diff --git a/integration/testUtils/index.ts b/integration/testUtils/index.ts index 3ab321d6b36..fd7de347e1f 100644 --- a/integration/testUtils/index.ts +++ b/integration/testUtils/index.ts @@ -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; }); }, diff --git a/integration/tests/sign-out-smoke.test.ts b/integration/tests/sign-out-smoke.test.ts new file mode 100644 index 00000000000..d7db869bc8a --- /dev/null +++ b/integration/tests/sign-out-smoke.test.ts @@ -0,0 +1,46 @@ +import { 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(); + }); + }); + + expect(await mainTab.page.evaluate('!window.Clerk.user')).toBe(false); + }); +}); From f2877bb546b524331ebd912009164f9557efb7f6 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 10 Nov 2023 12:05:05 +0200 Subject: [PATCH 5/7] chore(repo): Adds Changeset --- .changeset/dry-sheep-poke.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/dry-sheep-poke.md diff --git a/.changeset/dry-sheep-poke.md b/.changeset/dry-sheep-poke.md new file mode 100644 index 00000000000..a9dfccce204 --- /dev/null +++ b/.changeset/dry-sheep-poke.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': minor +--- + +Introducing sign out from all open tabs at once. From 66fafe8ec162696bab00a6632e8ef809e72d7f70 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 10 Nov 2023 13:58:24 +0200 Subject: [PATCH 6/7] fix(repo): Import expect form @playwright/test --- integration/tests/sign-out-smoke.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/sign-out-smoke.test.ts b/integration/tests/sign-out-smoke.test.ts index d7db869bc8a..06d6dac8190 100644 --- a/integration/tests/sign-out-smoke.test.ts +++ b/integration/tests/sign-out-smoke.test.ts @@ -1,4 +1,4 @@ -import { test } from '@playwright/test'; +import { expect, test } from '@playwright/test'; import { appConfigs } from '../presets'; import type { FakeUser } from '../testUtils'; From 339199067b9ca28fde64d8b08e0485a41fb62d99 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Fri, 10 Nov 2023 17:42:24 +0200 Subject: [PATCH 7/7] test(repo): Check if user is signed out --- integration/tests/sign-out-smoke.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration/tests/sign-out-smoke.test.ts b/integration/tests/sign-out-smoke.test.ts index 06d6dac8190..a6fa5a17964 100644 --- a/integration/tests/sign-out-smoke.test.ts +++ b/integration/tests/sign-out-smoke.test.ts @@ -39,6 +39,8 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign out await m.page.evaluate(async () => { await window.Clerk.signOut(); }); + + await m.po.expect.toBeSignedOut(); }); expect(await mainTab.page.evaluate('!window.Clerk.user')).toBe(false);