/* eslint-env jest */ import Vue from 'vue' import GuestPaystack from '@/ui-refactor/views/signup/components/GuestPaystack' describe('Guest Paystack component', () => { let vm let script let resumeTransaction let originalPopup beforeEach(() => { originalPopup = window.PaystackPop resumeTransaction = jest.fn() window.PaystackPop = jest.fn(() => ({ resumeTransaction })) vm = new Vue({ ...GuestPaystack, propsData: { paystackkey: 'pk_test_stub', email: 'test@example.invalid', amount: 873400, reference: 'test-reference', accessCode: 'test-access-code', callback: jest.fn(), close: jest.fn() } }) const scripts = document.querySelectorAll('script[src="https://js.paystack.co/v2/inline.js"]') script = scripts[scripts.length - 1] }) afterEach(() => { vm.$destroy() script.remove() window.PaystackPop = originalPopup }) it('uses the inherited component with V2 and resumes only the server access code', async() => { expect(script).toBeDefined() const pending = vm.payWithPaystack() vm.payWithPaystack() expect(resumeTransaction).not.toHaveBeenCalled() script.onload() await pending expect(window.PaystackPop).toHaveBeenCalledTimes(1) expect(resumeTransaction).toHaveBeenCalledTimes(1) expect(resumeTransaction).toHaveBeenCalledWith('test-access-code', { onSuccess: expect.any(Function), onCancel: expect.any(Function), onError: expect.any(Function) }) expect(resumeTransaction.mock.calls[0][1]).not.toHaveProperty('amount') expect(resumeTransaction.mock.calls[0][1]).not.toHaveProperty('reference') }) it('forwards the successful transaction reference', async() => { script.onload() await vm.payWithPaystack() const response = { reference: 'test-reference' } resumeTransaction.mock.calls[0][1].onSuccess(response) expect(vm.callback).toHaveBeenCalledWith(response) expect(vm.opening).toBe(false) }) it('opens checkout from the original component button', async() => { vm.$mount() expect(vm.$el.tagName).toBe('BUTTON') script.onload() vm.$el.click() await Promise.resolve() await Promise.resolve() expect(resumeTransaction).toHaveBeenCalledWith('test-access-code', expect.any(Object)) }) it('allows the same transaction to reopen after cancellation', async() => { script.onload() await vm.payWithPaystack() resumeTransaction.mock.calls[0][1].onCancel() expect(vm.close).toHaveBeenCalledTimes(1) expect(vm.opening).toBe(false) await vm.payWithPaystack() expect(resumeTransaction).toHaveBeenCalledTimes(2) expect(resumeTransaction.mock.calls.map(call => call[0])).toEqual(['test-access-code', 'test-access-code']) }) it('reports SDK load failures and does not start a payment', async() => { const errorHandler = jest.fn() vm.$on('error', errorHandler) script.onerror() await vm.payWithPaystack() expect(errorHandler).toHaveBeenCalledWith(expect.any(Error)) expect(resumeTransaction).not.toHaveBeenCalled() expect(vm.opening).toBe(false) }) it('reports errors from the checkout and permits retrying the same transaction', async() => { const errorHandler = jest.fn() vm.$on('error', errorHandler) script.onload() await vm.payWithPaystack() const error = new Error('Test checkout failure') resumeTransaction.mock.calls[0][1].onError(error) expect(errorHandler).toHaveBeenCalledWith(error) expect(vm.opening).toBe(false) await vm.payWithPaystack() expect(resumeTransaction).toHaveBeenCalledTimes(2) }) it('does not initialize a payment without an access code', async() => { const errorHandler = jest.fn() vm.$on('error', errorHandler) vm.accessCode = '' script.onload() await vm.payWithPaystack() expect(errorHandler).toHaveBeenCalledWith(expect.any(Error)) expect(resumeTransaction).not.toHaveBeenCalled() }) })