issue_card_spec.js 8.37 KB
Newer Older
1
/* global ListAssignee */
Phil Hughes's avatar
Phil Hughes committed
2 3 4
/* global ListLabel */
/* global ListIssue */

5
import Vue from 'vue';
Phil Hughes's avatar
Phil Hughes committed
6
import _ from 'underscore';
7 8

import '~/vue_shared/models/label';
9
import '~/vue_shared/models/assignee';
10 11
import '~/boards/models/issue';
import '~/boards/models/list';
12
import IssueCardInner from '~/boards/components/issue_card_inner.vue';
Eric Eastwood's avatar
Eric Eastwood committed
13
import { listObj } from './mock_data';
Phil Hughes's avatar
Phil Hughes committed
14 15

describe('Issue card component', () => {
16
  const user = new ListAssignee({
Phil Hughes's avatar
Phil Hughes committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
    id: 1,
    name: 'testing 123',
    username: 'test',
    avatar: 'test_image',
  });
  const label1 = new ListLabel({
    id: 3,
    title: 'testing 123',
    color: 'blue',
    text_color: 'white',
    description: 'test',
  });
  let component;
  let issue;
  let list;

  beforeEach(() => {
    setFixtures('<div class="test-container"></div>');

    list = listObj;
    issue = new ListIssue({
      title: 'Testing',
Simon Knox's avatar
Simon Knox committed
39
      id: 1,
Phil Hughes's avatar
Phil Hughes committed
40 41 42
      iid: 1,
      confidential: false,
      labels: [list.label],
43
      assignees: [],
Felipe Artur's avatar
Felipe Artur committed
44
      reference_path: '#1',
Felipe Artur's avatar
Felipe Artur committed
45
      real_path: '/test/1',
Phil Hughes's avatar
Phil Hughes committed
46 47 48 49
    });

    component = new Vue({
      el: document.querySelector('.test-container'),
50
      components: {
51
        'issue-card': IssueCardInner,
52
      },
Phil Hughes's avatar
Phil Hughes committed
53 54 55 56 57
      data() {
        return {
          list,
          issue,
          issueLinkBase: '/test',
Phil Hughes's avatar
Phil Hughes committed
58
          rootPath: '/',
Simon Knox's avatar
Simon Knox committed
59
          groupId: null,
Phil Hughes's avatar
Phil Hughes committed
60 61 62 63 64 65
        };
      },
      template: `
        <issue-card
          :issue="issue"
          :list="list"
Simon Knox's avatar
Simon Knox committed
66
          :group-id="groupId"
Phil Hughes's avatar
Phil Hughes committed
67 68
          :issue-link-base="issueLinkBase"
          :root-path="rootPath"></issue-card>
Phil Hughes's avatar
Phil Hughes committed
69 70 71 72 73
      `,
    });
  });

  it('renders issue title', () => {
74
    expect(component.$el.querySelector('.board-card-title').textContent).toContain(issue.title);
Phil Hughes's avatar
Phil Hughes committed
75 76 77
  });

  it('includes issue base in link', () => {
78 79 80
    expect(component.$el.querySelector('.board-card-title a').getAttribute('href')).toContain(
      '/test',
    );
Phil Hughes's avatar
Phil Hughes committed
81 82 83
  });

  it('includes issue title on link', () => {
84 85 86
    expect(component.$el.querySelector('.board-card-title a').getAttribute('title')).toBe(
      issue.title,
    );
Phil Hughes's avatar
Phil Hughes committed
87 88 89
  });

  it('does not render confidential icon', () => {
90
    expect(component.$el.querySelector('.fa-eye-flash')).toBeNull();
Phil Hughes's avatar
Phil Hughes committed
91 92
  });

93
  it('renders confidential icon', done => {
Phil Hughes's avatar
Phil Hughes committed
94 95
    component.issue.confidential = true;

96
    Vue.nextTick(() => {
97
      expect(component.$el.querySelector('.confidential-icon')).not.toBeNull();
Phil Hughes's avatar
Phil Hughes committed
98
      done();
99
    });
Phil Hughes's avatar
Phil Hughes committed
100 101 102
  });

  it('renders issue ID with #', () => {
103
    expect(component.$el.querySelector('.board-card-number').textContent).toContain(`#${issue.id}`);
Phil Hughes's avatar
Phil Hughes committed
104 105 106 107
  });

  describe('assignee', () => {
    it('does not render assignee', () => {
108
      expect(component.$el.querySelector('.board-card-assignee .avatar')).toBeNull();
Phil Hughes's avatar
Phil Hughes committed
109 110 111
    });

    describe('exists', () => {
112
      beforeEach(done => {
113
        component.issue.assignees = [user];
Phil Hughes's avatar
Phil Hughes committed
114

115
        Vue.nextTick(() => done());
Phil Hughes's avatar
Phil Hughes committed
116 117 118
      });

      it('renders assignee', () => {
119
        expect(component.$el.querySelector('.board-card-assignee .avatar')).not.toBeNull();
Phil Hughes's avatar
Phil Hughes committed
120 121 122
      });

      it('sets title', () => {
123 124 125
        expect(component.$el.querySelector('.js-assignee-tooltip').textContent).toContain(
          `${user.name}`,
        );
Phil Hughes's avatar
Phil Hughes committed
126 127 128
      });

      it('sets users path', () => {
129 130 131
        expect(component.$el.querySelector('.board-card-assignee a').getAttribute('href')).toBe(
          '/test',
        );
Phil Hughes's avatar
Phil Hughes committed
132 133 134
      });

      it('renders avatar', () => {
135
        expect(component.$el.querySelector('.board-card-assignee img')).not.toBeNull();
Phil Hughes's avatar
Phil Hughes committed
136 137
      });
    });
138 139

    describe('assignee default avatar', () => {
140 141 142 143 144 145 146 147 148 149 150
      beforeEach(done => {
        component.issue.assignees = [
          new ListAssignee(
            {
              id: 1,
              name: 'testing 123',
              username: 'test',
            },
            'default_avatar',
          ),
        ];
151 152 153 154 155

        Vue.nextTick(done);
      });

      it('displays defaults avatar if users avatar is null', () => {
156 157
        expect(component.$el.querySelector('.board-card-assignee img')).not.toBeNull();
        expect(component.$el.querySelector('.board-card-assignee img').getAttribute('src')).toBe(
158
          'default_avatar?width=24',
159
        );
160 161
      });
    });
Phil Hughes's avatar
Phil Hughes committed
162 163
  });

164
  describe('multiple assignees', () => {
165
    beforeEach(done => {
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
      component.issue.assignees = [
        new ListAssignee({
          id: 2,
          name: 'user2',
          username: 'user2',
          avatar: 'test_image',
        }),
        new ListAssignee({
          id: 3,
          name: 'user3',
          username: 'user3',
          avatar: 'test_image',
        }),
        new ListAssignee({
          id: 4,
          name: 'user4',
          username: 'user4',
          avatar: 'test_image',
184 185
        }),
      ];
186 187 188 189

      Vue.nextTick(() => done());
    });

190 191
    it('renders all three assignees', () => {
      expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(3);
192 193
    });

194
    describe('more than three assignees', () => {
195 196 197 198 199 200 201 202 203
      beforeEach(done => {
        component.issue.assignees.push(
          new ListAssignee({
            id: 5,
            name: 'user5',
            username: 'user5',
            avatar: 'test_image',
          }),
        );
204 205 206 207 208

        Vue.nextTick(() => done());
      });

      it('renders more avatar counter', () => {
209
        expect(
210
          component.$el.querySelector('.board-card-assignee .avatar-counter').innerText.trim(),
211
        ).toEqual('+2');
212 213
      });

214 215
      it('renders two assignees', () => {
        expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(2);
216 217
      });

218
      it('renders 99+ avatar counter', done => {
219 220 221 222 223 224 225 226 227 228 229
        for (let i = 5; i < 104; i += 1) {
          const u = new ListAssignee({
            id: i,
            name: 'name',
            username: 'username',
            avatar: 'test_image',
          });
          component.issue.assignees.push(u);
        }

        Vue.nextTick(() => {
230
          expect(
231
            component.$el.querySelector('.board-card-assignee .avatar-counter').innerText.trim(),
232
          ).toEqual('99+');
233 234 235 236 237 238
          done();
        });
      });
    });
  });

Phil Hughes's avatar
Phil Hughes committed
239
  describe('labels', () => {
240
    beforeEach(done => {
Simon Knox's avatar
Simon Knox committed
241
      component.issue.addLabel(label1);
Phil Hughes's avatar
Phil Hughes committed
242

Simon Knox's avatar
Simon Knox committed
243 244
      Vue.nextTick(() => done());
    });
Phil Hughes's avatar
Phil Hughes committed
245

Simon Knox's avatar
Simon Knox committed
246
    it('renders list label', () => {
247
      expect(component.$el.querySelectorAll('.badge').length).toBe(2);
Simon Knox's avatar
Simon Knox committed
248 249 250 251
    });

    it('renders label', () => {
      const nodes = [];
252
      component.$el.querySelectorAll('.badge').forEach(label => {
253
        nodes.push(label.getAttribute('data-original-title'));
Phil Hughes's avatar
Phil Hughes committed
254 255
      });

256
      expect(nodes.includes(label1.description)).toBe(true);
Simon Knox's avatar
Simon Knox committed
257
    });
Regis Boudinot's avatar
Regis Boudinot committed
258

Simon Knox's avatar
Simon Knox committed
259
    it('sets label description as title', () => {
260 261 262
      expect(component.$el.querySelector('.badge').getAttribute('data-original-title')).toContain(
        label1.description,
      );
Simon Knox's avatar
Simon Knox committed
263
    });
Phil Hughes's avatar
Phil Hughes committed
264

Simon Knox's avatar
Simon Knox committed
265 266
    it('sets background color of button', () => {
      const nodes = [];
267
      component.$el.querySelectorAll('.badge').forEach(label => {
Simon Knox's avatar
Simon Knox committed
268
        nodes.push(label.style.backgroundColor);
Phil Hughes's avatar
Phil Hughes committed
269 270
      });

271
      expect(nodes.includes(label1.color)).toBe(true);
Simon Knox's avatar
Simon Knox committed
272
    });
Regis Boudinot's avatar
Regis Boudinot committed
273

274 275 276 277 278 279
    it('does not render label if label does not have an ID', done => {
      component.issue.addLabel(
        new ListLabel({
          title: 'closed',
        }),
      );
280

Simon Knox's avatar
Simon Knox committed
281 282
      Vue.nextTick()
        .then(() => {
283 284
          expect(component.$el.querySelectorAll('.badge').length).toBe(2);
          expect(component.$el.textContent).not.toContain('closed');
285

Simon Knox's avatar
Simon Knox committed
286 287 288 289 290
          done();
        })
        .catch(done.fail);
    });

291 292 293 294 295 296 297 298
    it('shows group labels on group boards', done => {
      component.issue.addLabel(
        new ListLabel({
          id: _.random(10000),
          title: 'Group label',
          type: 'GroupLabel',
        }),
      );
Simon Knox's avatar
Simon Knox committed
299 300 301 302
      component.groupId = 1;

      Vue.nextTick()
        .then(() => {
303
          expect(component.$el.querySelectorAll('.badge').length).toBe(3);
304

305
          expect(component.$el.textContent).toContain('Group label');
Simon Knox's avatar
Simon Knox committed
306 307 308 309 310 311

          done();
        })
        .catch(done.fail);
    });

312 313 314 315 316 317 318 319
    it('shows project labels on group boards', done => {
      component.issue.addLabel(
        new ListLabel({
          id: 123,
          title: 'Project label',
          type: 'ProjectLabel',
        }),
      );
Simon Knox's avatar
Simon Knox committed
320 321 322 323
      component.groupId = 1;

      Vue.nextTick()
        .then(() => {
324
          expect(component.$el.querySelectorAll('.badge').length).toBe(3);
325

326
          expect(component.$el.textContent).toContain('Project label');
Simon Knox's avatar
Simon Knox committed
327 328 329 330

          done();
        })
        .catch(done.fail);
Phil Hughes's avatar
Phil Hughes committed
331 332 333
    });
  });
});