summaryrefslogtreecommitdiff
path: root/spec/frontend/confirm_modal_spec.js
blob: 70076532a944ba620371900d901823a7c56aeb93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import initConfirmModal from '~/confirm_modal';

describe('ConfirmModal', () => {
  const buttons = [
    {
      path: `${TEST_HOST}/1`,
      method: 'delete',
      modalAttributes: {
        title: 'Remove tracking database entry',
        message: 'Tracking database entry will be removed. Are you sure?',
        okVariant: 'danger',
        okTitle: 'Remove entry',
      },
    },
    {
      path: `${TEST_HOST}/1`,
      method: 'post',
      modalAttributes: {
        title: 'Update tracking database entry',
        message: 'Tracking database entry will be updated. Are you sure?',
        okVariant: 'success',
        okTitle: 'Update entry',
      },
    },
  ];

  beforeEach(() => {
    const buttonContainer = document.createElement('div');

    buttons.forEach(x => {
      const button = document.createElement('button');
      button.setAttribute('class', 'js-confirm-modal-button');
      button.setAttribute('data-path', x.path);
      button.setAttribute('data-method', x.method);
      button.setAttribute('data-modal-attributes', JSON.stringify(x.modalAttributes));
      button.innerHTML = 'Action';
      buttonContainer.appendChild(button);
    });

    document.body.appendChild(buttonContainer);
  });

  afterEach(() => {
    document.body.innerHTML = '';
  });

  const findJsHooks = () => document.querySelectorAll('.js-confirm-modal-button');
  const findModal = () => document.querySelector('.gl-modal');
  const findModalOkButton = (modal, variant) =>
    modal.querySelector(`.modal-footer .btn-${variant}`);
  const findModalCancelButton = modal => modal.querySelector('.modal-footer .btn-secondary');
  const modalIsHidden = () => findModal() === null;

  const serializeModal = (modal, buttonIndex) => {
    const { modalAttributes } = buttons[buttonIndex];

    return {
      path: modal.querySelector('form').action,
      method: modal.querySelector('input[name="_method"]').value,
      modalAttributes: {
        title: modal.querySelector('.modal-title').innerHTML,
        message: modal.querySelector('.modal-body div').innerHTML,
        okVariant: [...findModalOkButton(modal, modalAttributes.okVariant).classList]
          .find(x => x.match('btn-'))
          .replace('btn-', ''),
        okTitle: findModalOkButton(modal, modalAttributes.okVariant).innerHTML,
      },
    };
  };

  it('starts with only JsHooks', () => {
    expect(findJsHooks()).toHaveLength(buttons.length);
    expect(findModal()).not.toExist();
  });

  describe('when button clicked', () => {
    beforeEach(() => {
      initConfirmModal();
      findJsHooks()
        .item(0)
        .click();
    });

    it('does not replace JsHook with GlModal', () => {
      expect(findJsHooks()).toHaveLength(buttons.length);
    });

    describe('GlModal', () => {
      it('is rendered', () => {
        expect(findModal()).toExist();
        expect(modalIsHidden()).toBe(false);
      });

      describe('Cancel Button', () => {
        beforeEach(() => {
          findModalCancelButton(findModal()).click();

          return Vue.nextTick();
        });

        it('closes the modal', () => {
          setImmediate(() => {
            expect(modalIsHidden()).toBe(true);
          });
        });
      });
    });
  });

  describe.each`
    index
    ${0}
    ${1}
  `(`when multiple buttons exist`, ({ index }) => {
    beforeEach(() => {
      initConfirmModal();
      findJsHooks()
        .item(index)
        .click();
    });

    it('correct props are passed to gl-modal', () => {
      expect(serializeModal(findModal(), index)).toEqual(buttons[index]);
    });
  });
});