/* eslint-env jest */ import Vue from 'vue' import ElementUI from 'element-ui' import path from 'path' import { load } from '@/ui-refactor/views/purchase/__tests__/loadComponent' jest.mock('@/utils/usersInfo', () => ({})) Vue.use(ElementUI) const PaymentMethods = load(path.resolve('src/ui-refactor/components/PaymentMethods.vue')) const options = Object.freeze([ Object.freeze({ label: 'pay_stack', name: 'Paystack' }), Object.freeze({ label: 'cash', name: 'Ecoin' }), Object.freeze({ label: 'prp', name: 'PRP' }), Object.freeze({ label: 'other', name: 'Other returned method' }) ]) const instances = [] function mount(overrides = {}) { const changed = jest.fn() const vm = new Vue({ data: () => ({ options, selection: 'pay_stack', disabled: false, formDisabled: false, balances: { cash: 43, prp: 0 }, summary: Object.freeze({ amount: 90000, balance: 43, remaining: 0, insufficient: true }), ...overrides }), render(h) { return h('el-form', { props: { disabled: this.formDisabled }}, [h(PaymentMethods, { props: { options: this.options, value: this.selection, currency: 'NGN', balances: this.balances, summary: this.summary, disabled: this.disabled }, on: { input: value => { this.selection = value; changed(value) } } })]) } }).$mount() instances.push(vm) return { vm, changed } } afterEach(() => instances.splice(0).forEach(vm => vm.$destroy())) const inputs = vm => Array.from(vm.$el.querySelectorAll('input[type="radio"]')) it.each([options, Object.fromEntries(options.map(option => [option.label, option]))])('preserves returned option order and emits the original selected label once', async returned => { const { vm, changed } = mount({ options: returned }) expect(inputs(vm).map(input => input.value)).toEqual(options.map(option => option.label)) expect(changed).not.toHaveBeenCalled() inputs(vm).find(input => input.value === 'cash').click() await Vue.nextTick() expect(vm.selection).toBe('cash') expect(changed).toHaveBeenCalledTimes(1) expect(changed).toHaveBeenCalledWith('cash') expect(vm.summary.amount).toBe(90000) expect(vm.balances.cash).toBe(43) expect(vm.$el.textContent).toContain('not enough to cover this order') }) it('displays parent-provided totals, remaining balance and warning state without recalculating them', () => { const { vm } = mount({ selection: 'cash', summary: Object.freeze({ amount: 90000, balance: 43, remaining: 123, insufficient: false }) }) expect(Array.from(vm.$el.querySelectorAll('.el-descriptions-item__content'), node => node.textContent.trim())).toEqual(['NGN 43', 'NGN 90,000', 'NGN 123']) expect(vm.$el.querySelector('[role="alert"]')).toBeNull() }) it('supports a single returned option and distinguishes zero from missing amounts', () => { const { vm } = mount({ selection: 'cash', options: [options[1]], balances: { cash: 0 }, summary: { amount: 0, balance: 0, remaining: null, insufficient: false }}) expect(inputs(vm)).toHaveLength(1) expect(vm.$el.textContent).not.toContain('Paystack') expect(Array.from(vm.$el.querySelectorAll('.el-descriptions-item__content'), node => node.textContent.trim())).toEqual(['NGN 0', 'NGN 0', '—']) }) it('does not choose another method when the selected option is absent', async() => { const { vm, changed } = mount({ options: [options[1]] }) await Vue.nextTick() expect(vm.$el.querySelector('.ng-payment-methods-detail')).toBeNull() expect(vm.selection).toBe('pay_stack') expect(changed).not.toHaveBeenCalled() }) it.each(['disabled', 'formDisabled'])('keeps selection locked when %s is true', async field => { const { vm, changed } = mount({ [field]: true }) expect(inputs(vm).every(input => input.disabled)).toBe(true) inputs(vm).find(input => input.value === 'cash').click() await Vue.nextTick() expect(vm.selection).toBe('pay_stack') expect(changed).not.toHaveBeenCalled() })