issue_spec.js 6.57 KB
Newer Older
1
/* eslint-disable one-var, no-use-before-define */
2 3

import $ from 'jquery';
Phil Hughes's avatar
Phil Hughes committed
4
import MockAdapter from 'axios-mock-adapter';
Phil Hughes's avatar
Phil Hughes committed
5
import axios from '~/lib/utils/axios_utils';
6
import Issue from '~/issue';
7
import '~/lib/utils/text_utility';
Fatih Acet's avatar
Fatih Acet committed
8

9 10 11 12 13 14 15
describe('Issue', () => {
  let testContext;

  beforeEach(() => {
    testContext = {};
  });

16
  let $boxClosed, $boxOpen, $btn;
winniehell's avatar
winniehell committed
17

18 19 20
  preloadFixtures('issues/closed-issue.html');
  preloadFixtures('issues/issue-with-task-list.html');
  preloadFixtures('issues/open-issue.html');
21

winniehell's avatar
winniehell committed
22
  function expectErrorMessage() {
23
    const $flashMessage = $('div.flash-alert');
24

winniehell's avatar
winniehell committed
25 26 27 28 29 30 31 32
    expect($flashMessage).toExist();
    expect($flashMessage).toBeVisible();
    expect($flashMessage).toHaveText('Unable to update this issue at this time.');
  }

  function expectIssueState(isIssueOpen) {
    expectVisibility($boxClosed, !isIssueOpen);
    expectVisibility($boxOpen, isIssueOpen);
33

34
    expect($btn).toHaveText(isIssueOpen ? 'Close issue' : 'Reopen issue');
winniehell's avatar
winniehell committed
35 36
  }

37 38 39 40 41 42
  function expectNewBranchButtonState(isPending, canCreate) {
    if (Issue.$btnNewBranch.length === 0) {
      return;
    }

    const $available = Issue.$btnNewBranch.find('.available');
43

44 45 46 47 48 49 50 51 52
    expect($available).toHaveText('New branch');

    if (!isPending && canCreate) {
      expect($available).toBeVisible();
    } else {
      expect($available).toBeHidden();
    }

    const $unavailable = Issue.$btnNewBranch.find('.unavailable');
53

54 55 56 57 58 59 60
    expect($unavailable).toHaveText('New branch unavailable');

    if (!isPending && !canCreate) {
      expect($unavailable).toBeVisible();
    } else {
      expect($unavailable).toBeHidden();
    }
winniehell's avatar
winniehell committed
61 62 63 64 65 66 67 68 69 70
  }

  function expectVisibility($element, shouldBeVisible) {
    if (shouldBeVisible) {
      expect($element).not.toHaveClass('hidden');
    } else {
      expect($element).toHaveClass('hidden');
    }
  }

71
  function findElements(isIssueInitiallyOpen) {
72
    $boxClosed = $('div.status-box-issue-closed');
73

74 75
    expect($boxClosed).toExist();
    expect($boxClosed).toHaveText('Closed');
winniehell's avatar
winniehell committed
76

77
    $boxOpen = $('div.status-box-open');
78

79 80
    expect($boxOpen).toExist();
    expect($boxOpen).toHaveText('Open');
winniehell's avatar
winniehell committed
81

82
    $btn = $('.js-issuable-close-button');
83

84 85
    expect($btn).toExist();
    expect($btn).toHaveText(isIssueInitiallyOpen ? 'Close issue' : 'Reopen issue');
winniehell's avatar
winniehell committed
86 87
  }

Mike Greiling's avatar
Mike Greiling committed
88
  [true, false].forEach(isIssueInitiallyOpen => {
89
    describe(`with ${isIssueInitiallyOpen ? 'open' : 'closed'} issue`, () => {
90
      const action = isIssueInitiallyOpen ? 'close' : 'reopen';
Phil Hughes's avatar
Phil Hughes committed
91
      let mock;
92

93 94 95 96 97 98 99 100
      function setup() {
        testContext.issue = new Issue();
        expectIssueState(isIssueInitiallyOpen);

        testContext.$projectIssuesCounter = $('.issue_counter').first();
        testContext.$projectIssuesCounter.text('1,001');
      }

Phil Hughes's avatar
Phil Hughes committed
101 102 103 104 105 106 107 108 109 110 111 112
      function mockCloseButtonResponseSuccess(url, response) {
        mock.onPut(url).reply(() => {
          expectNewBranchButtonState(true, false);

          return [200, response];
        });
      }

      function mockCloseButtonResponseError(url) {
        mock.onPut(url).networkError();
      }

113 114 115
      function mockCanCreateBranch(canCreateBranch) {
        mock.onGet(/(.*)\/can_create_branch$/).reply(200, {
          can_create_branch: canCreateBranch,
116
          suggested_branch_name: 'foo-99',
117 118 119
        });
      }

120
      beforeEach(() => {
121
        if (isIssueInitiallyOpen) {
122
          loadFixtures('issues/open-issue.html');
123
        } else {
124
          loadFixtures('issues/closed-issue.html');
125 126
        }

127 128
        mock = new MockAdapter(axios);
        mock.onGet(/(.*)\/related_branches$/).reply(200, {});
129
        jest.spyOn(axios, 'get');
130

131
        findElements(isIssueInitiallyOpen);
132
        testContext.$triggeredButton = $btn;
133
      });
winniehell's avatar
winniehell committed
134

Phil Hughes's avatar
Phil Hughes committed
135 136
      afterEach(() => {
        mock.restore();
137
        $('div.flash-alert').remove();
Phil Hughes's avatar
Phil Hughes committed
138 139
      });

140 141
      it(`${action}s the issue`, done => {
        mockCloseButtonResponseSuccess(testContext.$triggeredButton.attr('href'), {
Mike Greiling's avatar
Mike Greiling committed
142
          id: 34,
Fatih Acet's avatar
Fatih Acet committed
143
        });
144
        mockCanCreateBranch(!isIssueInitiallyOpen);
Phil Hughes's avatar
Phil Hughes committed
145

146 147
        setup();
        testContext.$triggeredButton.trigger('click');
winniehell's avatar
winniehell committed
148

149
        setImmediate(() => {
Phil Hughes's avatar
Phil Hughes committed
150
          expectIssueState(!isIssueInitiallyOpen);
151

152 153 154 155
          expect(testContext.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
          expect(testContext.$projectIssuesCounter.text()).toBe(
            isIssueInitiallyOpen ? '1,000' : '1,002',
          );
Phil Hughes's avatar
Phil Hughes committed
156 157 158 159
          expectNewBranchButtonState(false, !isIssueInitiallyOpen);

          done();
        });
160
      });
winniehell's avatar
winniehell committed
161

162 163
      it(`fails to ${action} the issue if saved:false`, done => {
        mockCloseButtonResponseSuccess(testContext.$triggeredButton.attr('href'), {
Mike Greiling's avatar
Mike Greiling committed
164
          saved: false,
Fatih Acet's avatar
Fatih Acet committed
165
        });
166 167
        mockCanCreateBranch(isIssueInitiallyOpen);

168 169
        setup();
        testContext.$triggeredButton.trigger('click');
winniehell's avatar
winniehell committed
170

171
        setImmediate(() => {
Phil Hughes's avatar
Phil Hughes committed
172
          expectIssueState(isIssueInitiallyOpen);
173

174
          expect(testContext.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
Phil Hughes's avatar
Phil Hughes committed
175
          expectErrorMessage();
176

177
          expect(testContext.$projectIssuesCounter.text()).toBe('1,001');
Phil Hughes's avatar
Phil Hughes committed
178 179 180 181
          expectNewBranchButtonState(false, isIssueInitiallyOpen);

          done();
        });
Fatih Acet's avatar
Fatih Acet committed
182
      });
winniehell's avatar
winniehell committed
183

184 185
      it(`fails to ${action} the issue if HTTP error occurs`, done => {
        mockCloseButtonResponseError(testContext.$triggeredButton.attr('href'));
186 187
        mockCanCreateBranch(isIssueInitiallyOpen);

188 189
        setup();
        testContext.$triggeredButton.trigger('click');
190

191
        setImmediate(() => {
Phil Hughes's avatar
Phil Hughes committed
192
          expectIssueState(isIssueInitiallyOpen);
193

194
          expect(testContext.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
Phil Hughes's avatar
Phil Hughes committed
195
          expectErrorMessage();
196

197
          expect(testContext.$projectIssuesCounter.text()).toBe('1,001');
Phil Hughes's avatar
Phil Hughes committed
198 199 200 201
          expectNewBranchButtonState(false, isIssueInitiallyOpen);

          done();
        });
202
      });
winniehell's avatar
winniehell committed
203

204 205
      it('disables the new branch button if Ajax call fails', () => {
        mockCloseButtonResponseError(testContext.$triggeredButton.attr('href'));
206 207
        mock.onGet(/(.*)\/can_create_branch$/).networkError();

208 209
        setup();
        testContext.$triggeredButton.trigger('click');
winniehell's avatar
winniehell committed
210

211
        expectNewBranchButtonState(false, false);
Fatih Acet's avatar
Fatih Acet committed
212
      });
winniehell's avatar
winniehell committed
213

214 215 216 217 218
      it('does not trigger Ajax call if new branch button is missing', done => {
        mockCloseButtonResponseError(testContext.$triggeredButton.attr('href'));

        document.querySelector('#related-branches').remove();
        document.querySelector('.create-mr-dropdown-wrap').remove();
winniehell's avatar
winniehell committed
219

220 221
        setup();
        testContext.$triggeredButton.trigger('click');
222

223
        setImmediate(() => {
224 225 226 227
          expect(axios.get).not.toHaveBeenCalled();

          done();
        });
228
      });
Fatih Acet's avatar
Fatih Acet committed
229 230
    });
  });
231
});