OrganizationInvite.utils.test.ts126 lines · main
| 1 | import { describe, expect, test } from 'vitest' |
| 2 | |
| 3 | import { |
| 4 | getOrganizationInviteContent, |
| 5 | getOrganizationInviteStatus, |
| 6 | type OrganizationInviteStatus, |
| 7 | } from '@/components/interfaces/OrganizationInvite/OrganizationInvite.utils' |
| 8 | import type { OrganizationInviteByToken } from '@/data/organization-members/organization-invitation-token-query' |
| 9 | import type { ResponseError } from '@/types' |
| 10 | |
| 11 | const READY_INVITE: OrganizationInviteByToken = { |
| 12 | authorized_user: true, |
| 13 | email_match: true, |
| 14 | expired_token: false, |
| 15 | invite_id: 42, |
| 16 | organization_name: 'Acme Corp', |
| 17 | sso_mismatch: false, |
| 18 | token_does_not_exist: false, |
| 19 | } |
| 20 | |
| 21 | const responseError = (message: string, code = 500) => ({ message, code }) as ResponseError |
| 22 | type StatusOverrides = Partial<Parameters<typeof getOrganizationInviteStatus>[0]> |
| 23 | |
| 24 | const getStatus = (overrides: StatusOverrides = {}) => |
| 25 | getOrganizationInviteStatus({ |
| 26 | data: READY_INVITE, |
| 27 | error: null, |
| 28 | isErrorInvitation: false, |
| 29 | isLoadingInvitation: false, |
| 30 | isLoadingProfile: false, |
| 31 | isLoggedIn: true, |
| 32 | isRouterReady: true, |
| 33 | isSuccessInvitation: true, |
| 34 | profileExists: true, |
| 35 | ...overrides, |
| 36 | }) |
| 37 | |
| 38 | describe('OrganizationInvite utils', () => { |
| 39 | test.each<[string, OrganizationInviteStatus, StatusOverrides]>([ |
| 40 | ['signed out when there is no current user', 'signed-out', { isLoggedIn: false }], |
| 41 | ['loading while the profile is loading', 'loading', { isLoadingProfile: true }], |
| 42 | ['loading while the invite is loading', 'loading', { isLoadingInvitation: true }], |
| 43 | [ |
| 44 | 'no longer valid for accepted or declined invites', |
| 45 | 'no-longer-valid', |
| 46 | { |
| 47 | data: undefined, |
| 48 | error: responseError('Failed to retrieve organization', 401), |
| 49 | isErrorInvitation: true, |
| 50 | isSuccessInvitation: false, |
| 51 | }, |
| 52 | ], |
| 53 | [ |
| 54 | 'invalid when the API returns a missing token response', |
| 55 | 'invalid', |
| 56 | { |
| 57 | data: { ...READY_INVITE, token_does_not_exist: true }, |
| 58 | }, |
| 59 | ], |
| 60 | [ |
| 61 | 'invalid when the invite lookup 404s', |
| 62 | 'invalid', |
| 63 | { |
| 64 | data: undefined, |
| 65 | error: responseError('Not Found', 404), |
| 66 | isErrorInvitation: true, |
| 67 | isSuccessInvitation: false, |
| 68 | }, |
| 69 | ], |
| 70 | [ |
| 71 | 'error for other API failures', |
| 72 | 'error', |
| 73 | { |
| 74 | data: undefined, |
| 75 | error: responseError('Failed to retrieve token', 500), |
| 76 | isErrorInvitation: true, |
| 77 | isSuccessInvitation: false, |
| 78 | }, |
| 79 | ], |
| 80 | [ |
| 81 | 'expired when the token has expired', |
| 82 | 'expired', |
| 83 | { |
| 84 | data: { ...READY_INVITE, expired_token: true }, |
| 85 | }, |
| 86 | ], |
| 87 | [ |
| 88 | 'wrong account when the invite email does not match', |
| 89 | 'wrong-account', |
| 90 | { |
| 91 | data: { ...READY_INVITE, email_match: false }, |
| 92 | }, |
| 93 | ], |
| 94 | ['ready when the invite can be accepted', 'ready', {}], |
| 95 | ])('returns %s', (_name, expected, overrides) => { |
| 96 | expect(getStatus(overrides)).toBe(expected) |
| 97 | }) |
| 98 | |
| 99 | test.each<[OrganizationInviteStatus, string, string | undefined]>([ |
| 100 | ['signed-out', 'View invitation', 'Sign in or create an account to view this invitation'], |
| 101 | ['ready', 'Join Acme Corp', 'You have been invited to join this Briven organization'], |
| 102 | ['wrong-account', 'Wrong account', undefined], |
| 103 | ['expired', 'Invite expired', undefined], |
| 104 | ['invalid', 'Invite invalid', undefined], |
| 105 | ['no-longer-valid', 'Invite no longer available', undefined], |
| 106 | ['error', 'Unable to load invitation', undefined], |
| 107 | ])('returns content for %s', (status, title, description) => { |
| 108 | expect( |
| 109 | getOrganizationInviteContent({ |
| 110 | data: READY_INVITE, |
| 111 | isSignUpEnabled: true, |
| 112 | status, |
| 113 | }) |
| 114 | ).toEqual({ title, ...(description ? { description } : {}) }) |
| 115 | }) |
| 116 | |
| 117 | test('omits sign-up copy when sign-up is disabled', () => { |
| 118 | expect( |
| 119 | getOrganizationInviteContent({ |
| 120 | data: READY_INVITE, |
| 121 | isSignUpEnabled: false, |
| 122 | status: 'signed-out', |
| 123 | }).description |
| 124 | ).toBe('Sign in to view this invitation') |
| 125 | }) |
| 126 | }) |