Skip to content

Commit 09dbafc

Browse files
test(mosaic): cover OrganizationProfile and the switcher profile modals in integration tests
1 parent 5764aec commit 09dbafc

3 files changed

Lines changed: 99 additions & 2 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use client';
2+
3+
import { MosaicProvider, OrganizationProfile } from '@clerk/mosaic';
4+
5+
export default function Page() {
6+
return (
7+
<MosaicProvider>
8+
<OrganizationProfile
9+
customPages={[{ label: 'Custom page', path: 'custom-page', content: <p>custom-page-content</p> }]}
10+
/>
11+
</MosaicProvider>
12+
);
13+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import type { Organization } from '@clerk/backend';
2+
import type { BrowserContext, Page } from '@playwright/test';
3+
import { expect, test } from '@playwright/test';
4+
5+
import type { FakeUser } from '../../testUtils';
6+
import { createTestUtils, testAgainstRunningApps } from '../../testUtils';
7+
8+
testAgainstRunningApps({ withPattern: ['next.appRouterMosaic.*'] })('Mosaic OrganizationProfile @mosaic', ({ app }) => {
9+
test.describe.configure({ mode: 'serial' });
10+
11+
let fakeUser: FakeUser;
12+
let organization: Organization;
13+
const cleanups: Array<() => Promise<unknown>> = [];
14+
15+
test.beforeAll(async () => {
16+
const u = await createTestUtils({ app });
17+
fakeUser = u.services.users.createFakeUser(test);
18+
cleanups.push(() => fakeUser.deleteIfExists());
19+
const user = await u.services.users.createBapiUser(fakeUser);
20+
organization = await u.services.clerk.organizations.createOrganization({
21+
name: `Mosaic ${Date.now()}`,
22+
createdBy: user.id,
23+
});
24+
cleanups.push(() => u.services.clerk.organizations.deleteOrganization(organization.id));
25+
});
26+
27+
test.afterAll(async () => {
28+
const results = await Promise.allSettled(cleanups.map(cleanup => cleanup()));
29+
await app.teardown();
30+
const failures = results.flatMap(result => (result.status === 'rejected' ? [result.reason] : []));
31+
if (failures.length > 0) {
32+
throw new AggregateError(failures, 'Mosaic OrganizationProfile cleanup failed');
33+
}
34+
});
35+
36+
const path = '/organization-profile';
37+
const tab = (page: Page, name: string) => page.getByRole('tab', { name, exact: true });
38+
39+
async function signIn({ page, context }: { page: Page; context: BrowserContext }) {
40+
const u = await createTestUtils({ app, page, context });
41+
await page.setViewportSize({ width: 1280, height: 800 });
42+
await u.po.signIn.goTo();
43+
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
44+
await u.page.goToRelative(path);
45+
await u.po.expect.toBeSignedIn();
46+
await page.evaluate(orgId => window.Clerk?.setActive({ organization: orgId }), organization.id);
47+
await page.waitForFunction(orgId => window.Clerk?.organization?.id === orgId, organization.id);
48+
await expect(tab(page, 'General')).toBeVisible();
49+
return u;
50+
}
51+
52+
test('renders nothing when signed out', async ({ page, context }) => {
53+
const u = await createTestUtils({ app, page, context });
54+
await u.page.goToRelative(path);
55+
await u.page.waitForClerkJsLoaded();
56+
57+
await expect(tab(page, 'General')).toHaveCount(0);
58+
});
59+
60+
test('opens on the general page with the active organization', async ({ page, context }) => {
61+
await signIn({ page, context });
62+
63+
await expect(tab(page, 'General')).toHaveAttribute('aria-selected', 'true');
64+
await expect(page.getByText(organization.name).first()).toBeVisible();
65+
});
66+
67+
test('switches to the members page', async ({ page, context }) => {
68+
await signIn({ page, context });
69+
70+
await tab(page, 'Members').click();
71+
72+
await expect(tab(page, 'Members')).toHaveAttribute('aria-selected', 'true');
73+
await expect(page.getByText(fakeUser.email)).toBeVisible();
74+
});
75+
76+
test('renders a custom page', async ({ page, context }) => {
77+
await signIn({ page, context });
78+
79+
await tab(page, 'Custom page').click();
80+
await expect(page.getByText('custom-page-content')).toBeVisible();
81+
});
82+
});

‎integration/tests/mosaic/organization-switcher.test.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,15 @@ testAgainstRunningApps({ withPattern: ['next.appRouterMosaic.*'] })(
8686
});
8787

8888
test('renders a custom page inside the OrganizationProfile modal', async ({ page, context }) => {
89+
await page.setViewportSize({ width: 1280, height: 800 });
8990
await signIn({ page, context });
9091

9192
await trigger(page).click();
9293
await popup(page).getByRole('button', { name: 'Settings' }).click();
9394

94-
const profile = page.locator('.cl-organizationProfile-root');
95-
await profile.getByText('Custom page').click();
95+
await expect(page.getByRole('tab', { name: 'General', exact: true })).toHaveAttribute('aria-selected', 'true');
96+
await expect(page.locator('.cl-organizationProfile-root')).toHaveCount(0);
97+
await page.getByRole('tab', { name: 'Custom page', exact: true }).click();
9698
await expect(page.getByText('custom-page-content')).toBeVisible();
9799
});
98100
},

0 commit comments

Comments
 (0)