Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changeset/mosaic-user-profile-step3-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ describe('connected accounts', () => {
await waitFor(() => expect(navigate).toHaveBeenCalledWith('https://accounts.example/authorize'));
});

it('recreates a disconnected account', async () => {
serveFapi(signedIn([disconnectedGoogle]));
const { clerk } = await renderWithClerk(<UserProfileConnectedAccountsSection />);
it('recreates a disconnected account with the scopes the app requests', async () => {
serveFapi(signedIn([{ ...disconnectedGoogle, approved_scopes: '' }]));
const { clerk } = await renderWithClerk(
<UserProfileProvider additionalOAuthScopes={{ google: ['calendar'] }}>
<UserProfileConnectedAccountsSection />
</UserProfileProvider>,
);
const navigate = vi.spyOn(clerk, 'navigate').mockImplementation(() => Promise.resolve());
const request = holdRequests('post', '/v1/me/external_accounts');
const user = userEvent.setup();
Expand All @@ -68,6 +72,7 @@ describe('connected accounts', () => {
await waitFor(() => expect(request.requests).toHaveLength(1));
const body = new URLSearchParams(await request.requests[0]?.text());
expect(body.get('strategy')).toBe('oauth_google');
expect(body.getAll('additional_scope')).toEqual(['calendar']);
request.release();
await waitFor(() => expect(navigate).toHaveBeenCalledWith('https://accounts.example/authorize'));
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,19 @@ describe('the user profile email section', () => {
});
const { actor, clerk } = await renderSection(signedInWithEmails([PRIMARY, sso], verifiesByLink));
const windowNavigate = vi.spyOn(clerk, '__internal_windowNavigate').mockImplementation(() => {});
const prepare = holdRequests('post', '/v1/me/email_addresses/:id/prepare_verification');

await manageEmail(actor, 'alice@acme.co', 'Verify');
const dialog = await screen.findByRole('dialog', { name: 'Verify your email' });
expect(dialog).toHaveTextContent('acme.co');
expect(screen.queryByRole('textbox', { name: 'Verification code' })).not.toBeInTheDocument();
await actor.click(within(dialog).getByRole('button', { name: 'Connect' }));

await waitFor(() => expect(prepare.requests).toHaveLength(1));
const body = new URLSearchParams(await prepare.requests[0]?.text());
expect(body.get('strategy')).toBe('enterprise_sso');
expect(body.get('redirect_url')).toBe(window.location.href);
prepare.release();
await waitFor(() => expect(windowNavigate).toHaveBeenCalledWith(new URL('https://idp.acme.co/sso')));
});

Expand Down Expand Up @@ -211,6 +217,26 @@ describe('the user profile email section', () => {

expect(screen.queryByRole('group', { name: 'Email' })).not.toBeInTheDocument();
});

it('lists addresses but does not let the user remove them when it is immutable', async () => {
const secondary = fapiEmailAddress({
id: 'idn_secondary',
email_address: 'work@example.com',
verification: VERIFIED,
});
const { actor } = await renderSection(
signedInWithEmails(
[PRIMARY, secondary],
fapiEnvironment({ attributes: { email_address: { enabled: true, immutable: true } } }),
),
);

expect(emailsListed()).toEqual(['alice@example.com', 'work@example.com']);
expect(screen.queryByRole('button', { name: 'Add email' })).not.toBeInTheDocument();
await openMenu(actor, within(emailRow()).getByRole('button', { name: 'Manage work@example.com' }));
expect(screen.getByRole('menuitem', { name: 'Set as primary' })).toBeInTheDocument();
expect(screen.queryByRole('menuitem', { name: 'Remove email' })).not.toBeInTheDocument();
});
});

describe('the email section for a user signed in through an enterprise connection', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,18 @@ describe('Web3 wallet projection', () => {
});
});

it('does not offer Verify when wallet changes are disabled', () => {
it.each([
['wallet changes are disabled', 'unverified', ['web3_metamask_signature'], false],
['the wallet is already verified', 'verified', ['web3_metamask_signature'], true],
['the instance turned the provider off', 'unverified', ['web3_coinbase_wallet_signature'], true],
] as const)('does not offer Verify when %s', (_, status, enabledStrategies, allowCreation) => {
const result = projectWeb3Wallets({
wallets: [{ ...metamask, verification: { ...metamask.verification, status: 'unverified' } }],
wallets: [{ ...metamask, verification: { ...metamask.verification, status } }],
primaryId: null,
enabledStrategies: ['web3_metamask_signature'],
allowCreation: false,
});
expect(result).toMatchObject({
wallets: [{ id: 'wallet_metamask', canVerify: false }],
availableProviders: [],
enabledStrategies,
allowCreation,
});
expect(result).toMatchObject({ wallets: [{ id: 'wallet_metamask', canVerify: false }] });
});

it('WEB3-03 shows admin wallets without a provider and filters unknown strategies', () => {
Expand Down
Loading