UNPKG

@accounter/server

Version:
145 lines (124 loc) 4.67 kB
import { GraphQLError, GraphQLResolveInfo } from 'graphql'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { invitationsResolvers } from '../resolvers/invitations.resolver.js'; import { AcceptInvitationsProvider } from '../providers/accept-invitations.provider.js'; import { AuthContextProvider } from '../providers/auth-context.provider.js'; const acceptInvitation = invitationsResolvers.Mutation?.acceptInvitation as ( source: unknown, args: { token: string }, context: { injector: { get<T>(token: unknown): T } }, info: GraphQLResolveInfo, ) => Promise<{ success: boolean; businessId: string; roleId: string; }>; const mockInfo = {} as GraphQLResolveInfo; describe('acceptInvitation resolver', () => { let mockAuthProvider: { getAuthContext: ReturnType<typeof vi.fn>; getJwtIdentity: ReturnType<typeof vi.fn>; }; let mockAcceptInvitationsProvider: { acceptInvitation: ReturnType<typeof vi.fn> }; beforeEach(() => { mockAuthProvider = { getAuthContext: vi.fn().mockResolvedValue({ authType: 'jwt', user: { userId: 'caller-user-id', roleId: 'employee', email: 'invitee@example.com', permissions: [], emailVerified: true, permissionsVersion: 1, auth0UserId: 'auth0|caller-123', }, tenant: { businessId: 'business-123', roleId: 'employee', }, }), getJwtIdentity: vi.fn().mockResolvedValue(null), }; mockAcceptInvitationsProvider = { acceptInvitation: vi.fn().mockResolvedValue({ success: true, businessId: 'business-abc', roleId: 'employee', }), }; }); afterEach(() => { vi.clearAllMocks(); }); function createContext() { return { injector: { get<T>(token: unknown): T { if (token === AuthContextProvider) { return mockAuthProvider as T; } if (token === AcceptInvitationsProvider) { return mockAcceptInvitationsProvider as T; } throw new Error(`Unexpected token requested: ${String(token)}`); }, }, }; } it('delegates to AcceptInvitationsProvider and returns payload', async () => { const result = await acceptInvitation({}, { token: 'token-1' }, createContext(), mockInfo); expect(result).toEqual({ success: true, businessId: 'business-abc', roleId: 'employee', }); expect(mockAcceptInvitationsProvider.acceptInvitation).toHaveBeenCalledWith( 'token-1', 'auth0|caller-123', 'invitee@example.com', ); }); it('trims token before delegation', async () => { await acceptInvitation({}, { token: ' token-1 ' }, createContext(), mockInfo); expect(mockAcceptInvitationsProvider.acceptInvitation).toHaveBeenCalledWith( 'token-1', 'auth0|caller-123', 'invitee@example.com', ); }); it('empty token rejected with TOKEN_INVALID', async () => { await expect( acceptInvitation({}, { token: ' ' }, createContext(), mockInfo), ).rejects.toSatisfy(error => { return error instanceof GraphQLError && error.extensions?.code === 'TOKEN_INVALID'; }); expect(mockAcceptInvitationsProvider.acceptInvitation).not.toHaveBeenCalled(); }); it('unauthenticated user delegates with null auth0UserId', async () => { mockAuthProvider.getAuthContext.mockResolvedValueOnce(null); mockAuthProvider.getJwtIdentity.mockResolvedValueOnce(null); await acceptInvitation({}, { token: 'token-3' }, createContext(), mockInfo); expect(mockAcceptInvitationsProvider.acceptInvitation).toHaveBeenCalledWith('token-3', null, null); }); it('passes through GraphQLError from provider', async () => { mockAcceptInvitationsProvider.acceptInvitation.mockRejectedValueOnce( new GraphQLError('Invitation token expired', { extensions: { code: 'TOKEN_EXPIRED' }, }), ); await expect( acceptInvitation({}, { token: 'expired-token' }, createContext(), mockInfo), ).rejects.toSatisfy(error => { return error instanceof GraphQLError && error.extensions?.code === 'TOKEN_EXPIRED'; }); }); it('wraps non-GraphQLError failures as INVITATION_ACCEPT_FAILED', async () => { mockAcceptInvitationsProvider.acceptInvitation.mockRejectedValueOnce(new Error('boom')); await expect( acceptInvitation({}, { token: 'token-rollback' }, createContext(), mockInfo), ).rejects.toSatisfy(error => { return error instanceof GraphQLError && error.extensions?.code === 'INVITATION_ACCEPT_FAILED'; }); }); });