BigW Consortium Gitlab

merge_request_tabs_spec.js 15 KB
Newer Older
1
/* eslint-disable no-var, comma-dangle, object-shorthand */
2
/* global Notes */
Fatih Acet committed
3

4
import '~/merge_request_tabs';
Mike Greiling committed
5
import '~/commit/pipelines/pipelines_bundle';
6 7 8 9
import '~/breakpoints';
import '~/lib/utils/common_utils';
import '~/diff';
import '~/files_comment_button';
10
import '~/notes';
11
import 'vendor/jquery.scrollTo';
Fatih Acet committed
12

13 14 15 16 17
(function () {
  describe('MergeRequestTabs', function () {
    var stubLocation = {};
    var setLocation = function (stubs) {
      var defaults = {
Fatih Acet committed
18 19 20 21
        pathname: '',
        search: '',
        hash: ''
      };
22
      $.extend(stubLocation, defaults, stubs || {});
Fatih Acet committed
23
    };
24

25 26
    const inlineChangesTabJsonFixture = 'merge_request_diffs/inline_changes_tab_with_comments.json';
    const parallelChangesTabJsonFixture = 'merge_request_diffs/parallel_changes_tab_with_comments.json';
27 28 29 30 31 32
    preloadFixtures(
      'merge_requests/merge_request_with_task_list.html.raw',
      'merge_requests/diff_comment.html.raw',
      inlineChangesTabJsonFixture,
      parallelChangesTabJsonFixture
    );
33 34 35 36 37

    beforeEach(function () {
      this.class = new gl.MergeRequestTabs({ stubLocation: stubLocation });
      setLocation();

38 39 40
      this.spies = {
        history: spyOn(window.history, 'replaceState').and.callFake(function () {})
      };
Fatih Acet committed
41
    });
42

43
    afterEach(function () {
Alfredo Sumaran committed
44 45
      this.class.unbindEvents();
      this.class.destroyPipelinesView();
46 47
    });

48
    describe('activateTab', function () {
49
      beforeEach(function () {
Steffen Rauh committed
50
        spyOn($, 'ajax').and.callFake(function () {});
51
        loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
52
        this.subject = this.class.activateTab;
Fatih Acet committed
53
      });
54
      it('shows the notes tab when action is show', function () {
Fatih Acet committed
55
        this.subject('show');
56
        expect($('#notes')).toHaveClass('active');
Fatih Acet committed
57
      });
58
      it('shows the commits tab when action is commits', function () {
Fatih Acet committed
59
        this.subject('commits');
60
        expect($('#commits')).toHaveClass('active');
Fatih Acet committed
61
      });
62
      it('shows the diffs tab when action is diffs', function () {
Fatih Acet committed
63
        this.subject('diffs');
64
        expect($('#diffs')).toHaveClass('active');
Fatih Acet committed
65 66
      });
    });
Alfredo Sumaran committed
67

68
    describe('opensInNewTab', function () {
69
      var tabUrl;
70
      var windowTarget = '_blank';
71

72
      beforeEach(function () {
73 74 75
        loadFixtures('merge_requests/merge_request_with_task_list.html.raw');

        tabUrl = $('.commits-tab a').attr('href');
76 77

        spyOn($.fn, 'attr').and.returnValue(tabUrl);
78
      });
79 80

      describe('meta click', () => {
81
        let metakeyEvent;
82
        beforeEach(function () {
83
          metakeyEvent = $.Event('click', { keyCode: 91, ctrlKey: true });
84 85 86 87 88 89 90 91 92
        });

        it('opens page when commits link is clicked', function () {
          spyOn(window, 'open').and.callFake(function (url, name) {
            expect(url).toEqual(tabUrl);
            expect(name).toEqual(windowTarget);
          });

          this.class.bindEvents();
93
          $('.merge-request-tabs .commits-tab a').trigger(metakeyEvent);
94 95 96 97 98 99 100 101 102
        });

        it('opens page when commits badge is clicked', function () {
          spyOn(window, 'open').and.callFake(function (url, name) {
            expect(url).toEqual(tabUrl);
            expect(name).toEqual(windowTarget);
          });

          this.class.bindEvents();
103
          $('.merge-request-tabs .commits-tab a .badge').trigger(metakeyEvent);
104 105 106
        });
      });

107
      it('opens page tab in a new browser tab with Ctrl+Click - Windows/Linux', function () {
108 109
        spyOn(window, 'open').and.callFake(function (url, name) {
          expect(url).toEqual(tabUrl);
110
          expect(name).toEqual(windowTarget);
111
        });
112

113 114 115 116 117 118 119
        this.class.clickTab({
          metaKey: false,
          ctrlKey: true,
          which: 1,
          stopImmediatePropagation: function () {}
        });
      });
Alfredo Sumaran committed
120

121
      it('opens page tab in a new browser tab with Cmd+Click - Mac', function () {
122 123
        spyOn(window, 'open').and.callFake(function (url, name) {
          expect(url).toEqual(tabUrl);
124
          expect(name).toEqual(windowTarget);
125 126
        });

127 128 129 130 131 132 133
        this.class.clickTab({
          metaKey: true,
          ctrlKey: false,
          which: 1,
          stopImmediatePropagation: function () {}
        });
      });
Alfredo Sumaran committed
134

135
      it('opens page tab in a new browser tab with Middle-click - Mac/PC', function () {
136 137
        spyOn(window, 'open').and.callFake(function (url, name) {
          expect(url).toEqual(tabUrl);
138
          expect(name).toEqual(windowTarget);
139 140
        });

141 142 143 144 145 146 147
        this.class.clickTab({
          metaKey: false,
          ctrlKey: false,
          which: 2,
          stopImmediatePropagation: function () {}
        });
      });
148
    });
149

150
    describe('setCurrentAction', function () {
151
      beforeEach(function () {
Steffen Rauh committed
152
        spyOn($, 'ajax').and.callFake(function () {});
153
        this.subject = this.class.setCurrentAction;
Fatih Acet committed
154
      });
Alfredo Sumaran committed
155

156 157
      it('changes from commits', function () {
        setLocation({
Fatih Acet committed
158 159
          pathname: '/foo/bar/merge_requests/1/commits'
        });
160
        expect(this.subject('show')).toBe('/foo/bar/merge_requests/1');
161
        expect(this.subject('diffs')).toBe('/foo/bar/merge_requests/1/diffs');
Fatih Acet committed
162
      });
Alfredo Sumaran committed
163

164 165
      it('changes from diffs', function () {
        setLocation({
Fatih Acet committed
166 167
          pathname: '/foo/bar/merge_requests/1/diffs'
        });
Alfredo Sumaran committed
168

169
        expect(this.subject('show')).toBe('/foo/bar/merge_requests/1');
170
        expect(this.subject('commits')).toBe('/foo/bar/merge_requests/1/commits');
Fatih Acet committed
171
      });
Alfredo Sumaran committed
172

173 174
      it('changes from diffs.html', function () {
        setLocation({
Fatih Acet committed
175 176
          pathname: '/foo/bar/merge_requests/1/diffs.html'
        });
177
        expect(this.subject('show')).toBe('/foo/bar/merge_requests/1');
178
        expect(this.subject('commits')).toBe('/foo/bar/merge_requests/1/commits');
Fatih Acet committed
179
      });
Alfredo Sumaran committed
180

181 182
      it('changes from notes', function () {
        setLocation({
Fatih Acet committed
183 184 185
          pathname: '/foo/bar/merge_requests/1'
        });
        expect(this.subject('diffs')).toBe('/foo/bar/merge_requests/1/diffs');
186
        expect(this.subject('commits')).toBe('/foo/bar/merge_requests/1/commits');
Fatih Acet committed
187
      });
Alfredo Sumaran committed
188

189 190
      it('includes search parameters and hash string', function () {
        setLocation({
Fatih Acet committed
191 192 193 194
          pathname: '/foo/bar/merge_requests/1/diffs',
          search: '?view=parallel',
          hash: '#L15-35'
        });
195
        expect(this.subject('show')).toBe('/foo/bar/merge_requests/1?view=parallel#L15-35');
Fatih Acet committed
196
      });
Alfredo Sumaran committed
197

198 199 200
      it('replaces the current history state', function () {
        var newState;
        setLocation({
Fatih Acet committed
201 202
          pathname: '/foo/bar/merge_requests/1'
        });
203
        newState = this.subject('commits');
204 205 206
        expect(this.spies.history).toHaveBeenCalledWith({
          url: newState
        }, document.title, newState);
Fatih Acet committed
207
      });
Alfredo Sumaran committed
208

209 210
      it('treats "show" like "notes"', function () {
        setLocation({
Fatih Acet committed
211 212
          pathname: '/foo/bar/merge_requests/1/commits'
        });
213
        expect(this.subject('show')).toBe('/foo/bar/merge_requests/1');
Fatih Acet committed
214 215
      });
    });
216

217
    describe('tabShown', () => {
218
      beforeEach(function () {
219 220 221
        spyOn($, 'ajax').and.callFake(function (options) {
          options.success({ html: '' });
        });
222 223 224 225 226 227
        loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
      });

      describe('with "Side-by-side"/parallel diff view', () => {
        beforeEach(function () {
          this.class.diffViewType = () => 'parallel';
228
          gl.Diff.prototype.diffViewType = () => 'parallel';
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
        });

        it('maintains `container-limited` for pipelines tab', function (done) {
          const asyncClick = function (selector) {
            return new Promise((resolve) => {
              setTimeout(() => {
                document.querySelector(selector).click();
                resolve();
              });
            });
          };
          asyncClick('.merge-request-tabs .pipelines-tab a')
            .then(() => asyncClick('.merge-request-tabs .diffs-tab a'))
            .then(() => asyncClick('.merge-request-tabs .pipelines-tab a'))
            .then(() => {
              const hasContainerLimitedClass = document.querySelector('.content-wrapper .container-fluid').classList.contains('container-limited');
              expect(hasContainerLimitedClass).toBe(true);
            })
            .then(done)
            .catch((err) => {
              done.fail(`Something went wrong clicking MR tabs: ${err.message}\n${err.stack}`);
            });
        });
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

        it('maintains `container-limited` when switching from "Changes" tab before it loads', function (done) {
          const asyncClick = function (selector) {
            return new Promise((resolve) => {
              setTimeout(() => {
                document.querySelector(selector).click();
                resolve();
              });
            });
          };

          asyncClick('.merge-request-tabs .diffs-tab a')
            .then(() => asyncClick('.merge-request-tabs .notes-tab a'))
            .then(() => {
              const hasContainerLimitedClass = document.querySelector('.content-wrapper .container-fluid').classList.contains('container-limited');
              expect(hasContainerLimitedClass).toBe(true);
            })
            .then(done)
            .catch((err) => {
              done.fail(`Something went wrong clicking MR tabs: ${err.message}\n${err.stack}`);
            });
        });
274 275 276
      });
    });

277
    describe('loadDiff', function () {
278 279 280 281 282 283 284 285 286 287 288 289 290
      beforeEach(() => {
        loadFixtures('merge_requests/diff_comment.html.raw');
        spyOn(window.gl.utils, 'getPagePath').and.returnValue('merge_requests');
        window.gl.ImageFile = () => {};
        window.notes = new Notes('', []);
        spyOn(window.notes, 'toggleDiffNote').and.callThrough();
      });

      afterEach(() => {
        delete window.gl.ImageFile;
        delete window.notes;
      });

Steffen Rauh committed
291 292
      it('requires an absolute pathname', function () {
        spyOn($, 'ajax').and.callFake(function (options) {
293 294
          expect(options.url).toEqual('/foo/bar/merge_requests/1/diffs.json');
        });
295

296 297
        this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
      });
298 299 300 301 302 303 304 305 306 307 308

      it('triggers scroll event when diff already loaded', function () {
        spyOn(document, 'dispatchEvent');

        this.class.diffsLoaded = true;
        this.class.loadDiff('/foo/bar/merge_requests/1/diffs');

        expect(
          document.dispatchEvent,
        ).toHaveBeenCalledWith(new CustomEvent('scroll'));
      });
309

310 311 312 313
      describe('with inline diff', () => {
        let noteId;
        let noteLineNumId;

314
        beforeEach(() => {
315 316 317 318 319 320 321 322 323 324 325
          const diffsResponse = getJSONFixture(inlineChangesTabJsonFixture);

          const $html = $(diffsResponse.html);
          noteId = $html.find('.note').attr('id');
          noteLineNumId = $html
            .find('.note')
            .closest('.notes_holder')
            .prev('.line_holder')
            .find('a[data-linenumber]')
            .attr('href')
            .replace('#', '');
326

327 328 329
          spyOn($, 'ajax').and.callFake(function (options) {
            options.success(diffsResponse);
          });
330 331
        });

332 333 334 335 336 337 338 339 340 341 342
        describe('with note fragment hash', () => {
          it('should expand and scroll to linked fragment hash #note_xxx', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue(noteId);
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');

            expect(noteId.length).toBeGreaterThan(0);
            expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
              target: jasmine.any(Object),
              lineType: 'old',
              forceShow: true,
            });
343 344
          });

345 346 347
          it('should gracefully ignore non-existant fragment hash', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
348

349
            expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
350 351 352
          });
        });

353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
        describe('with line number fragment hash', () => {
          it('should gracefully ignore line number fragment hash', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue(noteLineNumId);
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');

            expect(noteLineNumId.length).toBeGreaterThan(0);
            expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
          });
        });
      });

      describe('with parallel diff', () => {
        let noteId;
        let noteLineNumId;

        beforeEach(() => {
          const diffsResponse = getJSONFixture(parallelChangesTabJsonFixture);

          const $html = $(diffsResponse.html);
          noteId = $html.find('.note').attr('id');
          noteLineNumId = $html
            .find('.note')
            .closest('.notes_holder')
            .prev('.line_holder')
            .find('a[data-linenumber]')
            .attr('href')
            .replace('#', '');

381
          spyOn($, 'ajax').and.callFake(function (options) {
382
            options.success(diffsResponse);
383
          });
384 385 386 387 388
        });

        describe('with note fragment hash', () => {
          it('should expand and scroll to linked fragment hash #note_xxx', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue(noteId);
389

390
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
391

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
            expect(noteId.length).toBeGreaterThan(0);
            expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({
              target: jasmine.any(Object),
              lineType: 'new',
              forceShow: true,
            });
          });

          it('should gracefully ignore non-existant fragment hash', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist');
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');

            expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
          });
        });

        describe('with line number fragment hash', () => {
          it('should gracefully ignore line number fragment hash', function () {
            spyOn(window.gl.utils, 'getLocationHash').and.returnValue(noteLineNumId);
            this.class.loadDiff('/foo/bar/merge_requests/1/diffs');

            expect(noteLineNumId.length).toBeGreaterThan(0);
            expect(window.notes.toggleDiffNote).not.toHaveBeenCalled();
          });
416 417
        });
      });
418
    });
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441

    describe('expandViewContainer', function () {
      beforeEach(() => {
        $('body').append('<div class="content-wrapper"><div class="container-fluid container-limited"></div></div>');
      });

      afterEach(() => {
        $('.content-wrapper').remove();
      });

      it('removes container-limited from containers', function () {
        this.class.expandViewContainer();

        expect($('.content-wrapper')).not.toContainElement('.container-limited');
      });

      it('does remove container-limited from breadcrumbs', function () {
        $('.container-limited').addClass('breadcrumbs');
        this.class.expandViewContainer();

        expect($('.content-wrapper')).toContainElement('.container-limited');
      });
    });
Fatih Acet committed
442
  });
443
}).call(window);