import {StatefulRemoteSubscribable} from '@remote-ui/async-subscription'; import {faker} from '@faker-js/faker'; import {ScopeNotGrantedError} from '../../errors'; import {useCustomer, useEmail, usePhone} from '../buyer-identity'; import {mount} from './mount'; function createMockCustomer(customer = {}) { const firstName = faker.name.firstName(); const lastName = faker.name.lastName(); return { id: `gid://shopify/Customer/${faker.datatype.number({ min: 1, precision: 1, })}`, fullName: `${firstName} ${lastName}`, firstName, lastName, email: faker.internet.email(), phone: faker.phone.number(), ...customer, }; } function createEmptyContext() { return { extensionApi: { buyerIdentity: undefined, }, }; } function createUseEmailContext(email?: string) { return createMockHookContext(email, undefined, undefined); } function createUseCustomerContext(customer = {}) { return createMockHookContext(undefined, undefined, customer); } function createUsePhoneContext(phone?: string) { return createMockHookContext(undefined, phone, undefined); } function createMockSuscribable(data: T): StatefulRemoteSubscribable { return { current: data, value: data, subscribe: () => () => {}, destroy: async () => {}, }; } function createMockHookContext(email?: string, phone?: string, customer = {}) { return { extensionApi: { buyerIdentity: { customer: createMockSuscribable(customer), email: createMockSuscribable(email), phone: createMockSuscribable(phone), }, }, }; } describe('buyerIdentity Hooks', () => { describe('useCustomer()', () => { it('raises an exception without CustomerPersonalData ApprovalScope', () => { expect(() => { mount.hook(() => useCustomer(), createEmptyContext()); }).toThrow(ScopeNotGrantedError); }); it('returns undefined fields with CustomerPersonalData ApprovalScopes only', () => { const hook = mount.hook( () => useCustomer(), createUseCustomerContext({ email: undefined, phone: undefined, firstName: undefined, lastName: undefined, fullName: undefined, }), ); expect(hook.current).toBeDefined(); expect(hook.current?.email).toBeUndefined(); expect(hook.current?.phone).toBeUndefined(); expect(hook.current?.fullName).toBeUndefined(); expect(hook.current?.firstName).toBeUndefined(); expect(hook.current?.lastName).toBeUndefined(); }); it('returns email, phone and name fields with all ApprovalScopes', () => { const customer = createMockCustomer(); const hook = mount.hook( () => useCustomer(), createUseCustomerContext(customer), ); expect(customer).toBeDefined(); expect(customer.email).toBeDefined(); expect(hook.current?.email).toBe(customer.email); expect(customer.phone).toBeDefined(); expect(hook.current?.phone).toBe(customer.phone); expect(customer.firstName).toBeDefined(); expect(hook.current?.firstName).toBe(customer.firstName); expect(customer.lastName).toBeDefined(); expect(hook.current?.lastName).toBe(customer.lastName); expect(customer.fullName).toBeDefined(); expect(hook.current?.fullName).toBe(customer.fullName); }); }); describe('useEmail()', () => { it('raises an exception without CustomerPersonalData ApprovalScope', () => { expect(() => { mount.hook(() => useEmail(), createEmptyContext()); }).toThrow(ScopeNotGrantedError); }); it('returns undefined with CustomerPersonalData ApprovalScope only', () => { const hook = mount.hook( () => useEmail(), createUseEmailContext(undefined), ); expect(hook?.current).toBeUndefined(); }); it('returns email with CustomerPersonalData and CustomerEmail ApprovalScopes', () => { const email = faker.internet.email(); const hook = mount.hook(() => useEmail(), createUseEmailContext(email)); expect(hook?.current).toBe(email); }); }); describe('usePhone()', () => { it('raises an exception without CustomerPersonalData ApprovalScope', () => { expect(() => { mount.hook(() => usePhone(), createEmptyContext()); }).toThrow(ScopeNotGrantedError); }); it('returns undefined with CustomerPersonalData ApprovalScope only', () => { const hook = mount.hook( () => usePhone(), createUsePhoneContext(undefined), ); expect(hook?.current).toBeUndefined(); }); it('returns phone with CustomerPersonalData and CustomerEmail ApprovalScopes', () => { const phone = faker.phone.number(); const hook = mount.hook(() => usePhone(), createUsePhoneContext(phone)); expect(hook?.current).toBe(phone); }); }); });