paymentMethods.spec.js 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /* eslint-env jest */
  2. import Vue from 'vue'
  3. import ElementUI from 'element-ui'
  4. import path from 'path'
  5. import { load } from '@/ui-refactor/views/purchase/__tests__/loadComponent'
  6. jest.mock('@/utils/usersInfo', () => ({}))
  7. Vue.use(ElementUI)
  8. const PaymentMethods = load(path.resolve('src/ui-refactor/components/PaymentMethods.vue'))
  9. const options = Object.freeze([
  10. Object.freeze({ label: 'pay_stack', name: 'Paystack' }),
  11. Object.freeze({ label: 'cash', name: 'Ecoin' }),
  12. Object.freeze({ label: 'prp', name: 'PRP' }),
  13. Object.freeze({ label: 'other', name: 'Other returned method' })
  14. ])
  15. const instances = []
  16. function mount(overrides = {}) {
  17. const changed = jest.fn()
  18. const vm = new Vue({
  19. data: () => ({
  20. options, selection: 'pay_stack', disabled: false, formDisabled: false,
  21. balances: { cash: 43, prp: 0 },
  22. summary: Object.freeze({ amount: 90000, balance: 43, remaining: 0, insufficient: true }),
  23. ...overrides
  24. }),
  25. render(h) {
  26. return h('el-form', { props: { disabled: this.formDisabled }}, [h(PaymentMethods, {
  27. props: { options: this.options, value: this.selection, currency: 'NGN', balances: this.balances, summary: this.summary, disabled: this.disabled },
  28. on: { input: value => { this.selection = value; changed(value) } }
  29. })])
  30. }
  31. }).$mount()
  32. instances.push(vm)
  33. return { vm, changed }
  34. }
  35. afterEach(() => instances.splice(0).forEach(vm => vm.$destroy()))
  36. const inputs = vm => Array.from(vm.$el.querySelectorAll('input[type="radio"]'))
  37. it.each([options, Object.fromEntries(options.map(option => [option.label, option]))])('preserves returned option order and emits the original selected label once', async returned => {
  38. const { vm, changed } = mount({ options: returned })
  39. expect(inputs(vm).map(input => input.value)).toEqual(options.map(option => option.label))
  40. expect(changed).not.toHaveBeenCalled()
  41. inputs(vm).find(input => input.value === 'cash').click()
  42. await Vue.nextTick()
  43. expect(vm.selection).toBe('cash')
  44. expect(changed).toHaveBeenCalledTimes(1)
  45. expect(changed).toHaveBeenCalledWith('cash')
  46. expect(vm.summary.amount).toBe(90000)
  47. expect(vm.balances.cash).toBe(43)
  48. expect(vm.$el.textContent).toContain('not enough to cover this order')
  49. })
  50. it('displays parent-provided totals, remaining balance and warning state without recalculating them', () => {
  51. const { vm } = mount({ selection: 'cash', summary: Object.freeze({ amount: 90000, balance: 43, remaining: 123, insufficient: false }) })
  52. expect(Array.from(vm.$el.querySelectorAll('.el-descriptions-item__content'), node => node.textContent.trim())).toEqual(['NGN 43', 'NGN 90,000', 'NGN 123'])
  53. expect(vm.$el.querySelector('[role="alert"]')).toBeNull()
  54. })
  55. it('supports a single returned option and distinguishes zero from missing amounts', () => {
  56. const { vm } = mount({ selection: 'cash', options: [options[1]], balances: { cash: 0 }, summary: { amount: 0, balance: 0, remaining: null, insufficient: false }})
  57. expect(inputs(vm)).toHaveLength(1)
  58. expect(vm.$el.textContent).not.toContain('Paystack')
  59. expect(Array.from(vm.$el.querySelectorAll('.el-descriptions-item__content'), node => node.textContent.trim())).toEqual(['NGN 0', 'NGN 0', '—'])
  60. })
  61. it('does not choose another method when the selected option is absent', async() => {
  62. const { vm, changed } = mount({ options: [options[1]] })
  63. await Vue.nextTick()
  64. expect(vm.$el.querySelector('.ng-payment-methods-detail')).toBeNull()
  65. expect(vm.selection).toBe('pay_stack')
  66. expect(changed).not.toHaveBeenCalled()
  67. })
  68. it.each(['disabled', 'formDisabled'])('keeps selection locked when %s is true', async field => {
  69. const { vm, changed } = mount({ [field]: true })
  70. expect(inputs(vm).every(input => input.disabled)).toBe(true)
  71. inputs(vm).find(input => input.value === 'cash').click()
  72. await Vue.nextTick()
  73. expect(vm.selection).toBe('pay_stack')
  74. expect(changed).not.toHaveBeenCalled()
  75. })