summaryrefslogtreecommitdiff
path: root/spec/javascripts/sidebar/sidebar_move_issue_spec.js
blob: 8f35b9ca43744197b1476df98fe9bbe03337fb23 (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import $ from 'jquery';
import _ from 'underscore';
import Vue from 'vue';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import SidebarStore from '~/sidebar/stores/sidebar_store';
import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
import Mock from './mock_data';

describe('SidebarMoveIssue', function () {
  beforeEach(() => {
    Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
    this.mediator = new SidebarMediator(Mock.mediator);
    this.$content = $(`
      <div class="dropdown">
        <div class="js-toggle"></div>
        <div class="dropdown-menu">
          <div class="dropdown-content"></div>
        </div>
        <div class="js-confirm-button"></div>
      </div>
    `);
    this.$toggleButton = this.$content.find('.js-toggle');
    this.$confirmButton = this.$content.find('.js-confirm-button');

    this.sidebarMoveIssue = new SidebarMoveIssue(
      this.mediator,
      this.$toggleButton,
      this.$confirmButton,
    );
    this.sidebarMoveIssue.init();
  });

  afterEach(() => {
    SidebarService.singleton = null;
    SidebarStore.singleton = null;
    SidebarMediator.singleton = null;

    this.sidebarMoveIssue.destroy();

    Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor);
  });

  describe('init', () => {
    it('should initialize the dropdown and listeners', () => {
      spyOn(this.sidebarMoveIssue, 'initDropdown');
      spyOn(this.sidebarMoveIssue, 'addEventListeners');

      this.sidebarMoveIssue.init();

      expect(this.sidebarMoveIssue.initDropdown).toHaveBeenCalled();
      expect(this.sidebarMoveIssue.addEventListeners).toHaveBeenCalled();
    });
  });

  describe('destroy', () => {
    it('should remove the listeners', () => {
      spyOn(this.sidebarMoveIssue, 'removeEventListeners');

      this.sidebarMoveIssue.destroy();

      expect(this.sidebarMoveIssue.removeEventListeners).toHaveBeenCalled();
    });
  });

  describe('initDropdown', () => {
    it('should initialize the gl_dropdown', () => {
      spyOn($.fn, 'glDropdown');

      this.sidebarMoveIssue.initDropdown();

      expect($.fn.glDropdown).toHaveBeenCalled();
    });

    it('escapes html from project name', (done) => {
      this.$toggleButton.dropdown('toggle');

      setTimeout(() => {
        expect(this.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual('&lt;img src=x onerror=alert(document.domain)&gt; foo / bar');
        done();
      });
    });
  });

  describe('onConfirmClicked', () => {
    it('should move the issue with valid project ID', () => {
      spyOn(this.mediator, 'moveIssue').and.returnValue(Promise.resolve());
      this.mediator.setMoveToProjectId(7);

      this.sidebarMoveIssue.onConfirmClicked();

      expect(this.mediator.moveIssue).toHaveBeenCalled();
      expect(this.$confirmButton.prop('disabled')).toBeTruthy();
      expect(this.$confirmButton.hasClass('is-loading')).toBe(true);
    });

    it('should remove loading state from confirm button on failure', (done) => {
      spyOn(window, 'Flash');
      spyOn(this.mediator, 'moveIssue').and.returnValue(Promise.reject());
      this.mediator.setMoveToProjectId(7);

      this.sidebarMoveIssue.onConfirmClicked();

      expect(this.mediator.moveIssue).toHaveBeenCalled();
      // Wait for the move issue request to fail
      setTimeout(() => {
        expect(window.Flash).toHaveBeenCalled();
        expect(this.$confirmButton.prop('disabled')).toBeFalsy();
        expect(this.$confirmButton.hasClass('is-loading')).toBe(false);
        done();
      });
    });

    it('should not move the issue with id=0', () => {
      spyOn(this.mediator, 'moveIssue');
      this.mediator.setMoveToProjectId(0);

      this.sidebarMoveIssue.onConfirmClicked();

      expect(this.mediator.moveIssue).not.toHaveBeenCalled();
    });
  });

  it('should set moveToProjectId on dropdown item "No project" click', (done) => {
    spyOn(this.mediator, 'setMoveToProjectId');

    // Open the dropdown
    this.$toggleButton.dropdown('toggle');

    // Wait for the autocomplete request to finish
    setTimeout(() => {
      this.$content.find('.js-move-issue-dropdown-item').eq(0).trigger('click');

      expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
      expect(this.$confirmButton.prop('disabled')).toBeTruthy();
      done();
    }, 0);
  });

  it('should set moveToProjectId on dropdown item click', (done) => {
    spyOn(this.mediator, 'setMoveToProjectId');

    // Open the dropdown
    this.$toggleButton.dropdown('toggle');

    // Wait for the autocomplete request to finish
    setTimeout(() => {
      this.$content.find('.js-move-issue-dropdown-item').eq(1).trigger('click');

      expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
      expect(this.$confirmButton.attr('disabled')).toBe(undefined);
      done();
    }, 0);
  });
});