Commit b7fa9dc4 authored by Martin Wortschack's avatar Martin Wortschack

Merge branch '34723-update-board-tests-to-use-vue-test-utils' into 'master'

Update board tests to use vue-test-utils

See merge request gitlab-org/gitlab!24452
parents ee79fa62 e5bf1b99
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import AssigneesListItem from 'ee/boards/components/boards_list_selector/assignees_list_item.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockAssigneesList } from 'jest/boards/mock_data';
const createComponent = () => {
const Component = Vue.extend(AssigneesListItem);
return mountComponent(Component, {
item: mockAssigneesList[0],
});
};
describe('AssigneesListItem', () => {
let vm;
const assignee = mockAssigneesList[0];
let wrapper;
beforeEach(() => {
vm = createComponent();
wrapper = shallowMount(AssigneesListItem, {
propsData: {
item: assignee,
},
});
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('computed', () => {
describe('avatarAltText', () => {
it('returns computed alt text based on assignee.name', () => {
expect(vm.avatarAltText).toBe(`${mockAssigneesList[0].name}'s avatar`);
});
});
it('renders component container element with class `filter-dropdown-item`', () => {
expect(wrapper.contains('.filter-dropdown-item')).toBe(true);
});
describe('methods', () => {
describe('handleItemClick', () => {
it('emits `onItemSelect` event on component and sends `assignee` as event param', () => {
jest.spyOn(vm, '$emit');
const assignee = mockAssigneesList[0];
it('emits `onItemSelect` event on component click and sends `assignee` as event param', () => {
wrapper.find('.filter-dropdown-item').trigger('click');
vm.handleItemClick();
expect(wrapper.emitted().onItemSelect[0]).toEqual([assignee]);
});
expect(vm.$emit).toHaveBeenCalledWith('onItemSelect', assignee);
describe('avatar', () => {
it('has alt text', () => {
expect(wrapper.find('.avatar').attributes('alt')).toBe(`${assignee.name}'s avatar`);
});
it('has src url', () => {
expect(wrapper.find('.avatar').attributes('src')).toBe(assignee.avatar_url);
});
});
describe('template', () => {
it('renders component container element with class `filter-dropdown-item`', () => {
expect(vm.$el.classList.contains('filter-dropdown-item')).toBe(true);
describe('user details', () => {
it('shows assignee name', () => {
expect(wrapper.find('.dropdown-user-details').text()).toContain(assignee.name);
});
it('renders user item button element', () => {
const assignee = mockAssigneesList[0];
const buttonEl = vm.$el.querySelector('.dropdown-user');
expect(buttonEl).not.toBeNull();
expect(
buttonEl.querySelector('.avatar-container.s32 img.avatar.s32').getAttribute('src'),
).toBe(assignee.avatar_url);
expect(buttonEl.querySelector('.dropdown-user-details').innerText).toContain(assignee.name);
expect(
buttonEl.querySelector('.dropdown-user-details .dropdown-light-content').innerText,
).toContain(`@${assignee.username}`);
it('shows assignee username', () => {
expect(wrapper.find('.dropdown-user-details .dropdown-light-content').text()).toContain(
`@${assignee.username}`,
);
});
});
});
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import ListContainer from 'ee/boards/components/boards_list_selector/list_container.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import ListFilter from 'ee/boards/components/boards_list_selector/list_filter.vue';
import ListContent from 'ee/boards/components/boards_list_selector/list_content.vue';
import { mockAssigneesList } from 'jest/boards/mock_data';
const createComponent = () => {
const Component = Vue.extend(ListContainer);
describe('ListContainer', () => {
let wrapper;
return mountComponent(Component, {
beforeEach(() => {
wrapper = shallowMount(ListContainer, {
propsData: {
loading: false,
items: mockAssigneesList,
listType: 'assignees',
},
});
};
describe('ListContainer', () => {
let vm;
beforeEach(() => {
vm = createComponent();
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('computed', () => {
describe('filteredItems', () => {
it('returns assignees list as it is when `query` is empty', () => {
vm.query = '';
wrapper.setData({ query: '' });
expect(vm.filteredItems.length).toBe(mockAssigneesList.length);
expect(wrapper.vm.filteredItems.length).toBe(mockAssigneesList.length);
});
it('returns filtered assignees list as it is when `query` has name', () => {
const assignee = mockAssigneesList[0];
vm.query = assignee.name;
wrapper.setData({ query: assignee.name });
expect(vm.filteredItems.length).toBe(1);
expect(vm.filteredItems[0].name).toBe(assignee.name);
expect(wrapper.vm.filteredItems.length).toBe(1);
expect(wrapper.vm.filteredItems[0].name).toBe(assignee.name);
});
it('returns filtered assignees list as it is when `query` has username', () => {
const assignee = mockAssigneesList[0];
vm.query = assignee.username;
wrapper.setData({ query: assignee.username });
expect(vm.filteredItems.length).toBe(1);
expect(vm.filteredItems[0].username).toBe(assignee.username);
expect(wrapper.vm.filteredItems.length).toBe(1);
expect(wrapper.vm.filteredItems[0].username).toBe(assignee.username);
});
});
});
......@@ -58,39 +54,39 @@ describe('ListContainer', () => {
describe('handleSearch', () => {
it('sets value of param `query` to component prop `query`', () => {
const query = 'foobar';
vm.handleSearch(query);
wrapper.vm.handleSearch(query);
expect(vm.query).toBe(query);
expect(wrapper.vm.query).toBe(query);
});
});
describe('handleItemClick', () => {
it('emits `onItemSelect` event on component and sends `assignee` as event param', () => {
jest.spyOn(vm, '$emit');
const assignee = mockAssigneesList[0];
vm.handleItemClick(assignee);
wrapper.vm.handleItemClick(assignee);
expect(vm.$emit).toHaveBeenCalledWith('onItemSelect', assignee);
expect(wrapper.emitted().onItemSelect[0]).toEqual([assignee]);
});
});
});
describe('template', () => {
it('renders component container element with class `dropdown-assignees-list`', () => {
expect(vm.$el.classList.contains('dropdown-assignees-list')).toBe(true);
expect(wrapper.classes('dropdown-assignees-list')).toBe(true);
});
it('renders loading animation when prop `loading` is true', () => {
vm.loading = true;
wrapper.setProps({ loading: true });
return Vue.nextTick().then(() => {
expect(vm.$el.querySelector('.dropdown-loading')).not.toBeNull();
expect(wrapper.find('.dropdown-loading').exists()).toBe(true);
});
});
it('renders dropdown body elements', () => {
expect(vm.$el.querySelector('.dropdown-input')).not.toBeNull();
expect(vm.$el.querySelector('.dropdown-content')).not.toBeNull();
expect(wrapper.find(ListFilter).exists()).toBe(true);
expect(wrapper.find(ListContent).exists()).toBe(true);
});
});
});
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import ListContent from 'ee/boards/components/boards_list_selector/list_content.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { mockAssigneesList } from 'jest/boards/mock_data';
const createComponent = () => {
const Component = Vue.extend(ListContent);
describe('ListContent', () => {
let wrapper;
return mountComponent(Component, {
beforeEach(() => {
wrapper = shallowMount(ListContent, {
propsData: {
items: mockAssigneesList,
listType: 'assignees',
},
});
};
describe('ListContent', () => {
let vm;
beforeEach(() => {
vm = createComponent();
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('methods', () => {
describe('handleItemClick', () => {
it('emits `onItemSelect` event on component and sends `assignee` as event param', () => {
jest.spyOn(vm, '$emit');
const assignee = mockAssigneesList[0];
vm.handleItemClick(assignee);
wrapper.vm.handleItemClick(assignee);
expect(vm.$emit).toHaveBeenCalledWith('onItemSelect', assignee);
});
});
expect(wrapper.emitted().onItemSelect[0]).toEqual([assignee]);
});
describe('template', () => {
it('renders component container element with class `dropdown-content`', () => {
expect(vm.$el.classList.contains('dropdown-content')).toBe(true);
expect(wrapper.classes('dropdown-content')).toBe(true);
});
it('renders UL parent element as child within container', () => {
expect(vm.$el.querySelector('ul')).not.toBeNull();
});
expect(wrapper.find('ul').exists()).toBe(true);
});
});
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import ListFilter from 'ee/boards/components/boards_list_selector/list_filter.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
const createComponent = () => {
const Component = Vue.extend(ListFilter);
return mountComponent(Component);
};
describe('ListFilter', () => {
let vm;
let wrapper;
beforeEach(() => {
vm = createComponent();
wrapper = shallowMount(ListFilter);
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('methods', () => {
describe('handleInputChange', () => {
it('emits `onSearchInput` event on component and sends `query` as event param', () => {
jest.spyOn(vm, '$emit');
const query = 'foobar';
vm.query = query;
describe('input field', () => {
it('emits `onSearchInput` event on keyup and sends input text as event param', () => {
const input = wrapper.find('input');
input.setValue('foobar');
input.trigger('keyup');
vm.handleInputChange();
expect(vm.$emit).toHaveBeenCalledWith('onSearchInput', query);
expect(wrapper.emitted().onSearchInput[0]).toEqual(['foobar']);
});
});
describe('handleInputClear', () => {
it('clears value of prop `query` and calls `handleInputChange` method on component', () => {
jest.spyOn(vm, 'handleInputChange');
vm.query = 'foobar';
describe('clear button', () => {
let input;
vm.handleInputClear();
beforeEach(() => {
// Pre-populate input field with text
input = wrapper.find('input');
input.setValue('foobar');
input.trigger('keyup');
});
expect(vm.query).toBe('');
expect(vm.handleInputChange).toHaveBeenCalled();
it('clears input field and emits `onSearchInput` event with empty value', () => {
expect(input.element.value).toBe('foobar');
wrapper.find('.dropdown-input-clear').trigger('click');
return Vue.nextTick().then(() => {
expect(input.element.value).toBe('');
expect(wrapper.emitted().onSearchInput[1]).toEqual(['']);
});
});
});
describe('template', () => {
it('renders component container element with class `dropdown-input`', () => {
expect(vm.$el.classList.contains('dropdown-input')).toBe(true);
expect(wrapper.classes('dropdown-input')).toBe(true);
});
it('renders class `has-value` on container element when prop `query` is not empty', () => {
vm.query = 'foobar';
wrapper.setData({ query: 'foobar' });
return Vue.nextTick().then(() => {
expect(vm.$el.classList.contains('has-value')).toBe(true);
expect(wrapper.classes('has-value')).toBe(true);
});
});
it('removes class `has-value` from container element when prop `query` is empty', () => {
vm.query = '';
wrapper.setData({ query: '' });
return Vue.nextTick().then(() => {
expect(vm.$el.classList.contains('has-value')).toBe(false);
expect(wrapper.classes('has-value')).toBe(false);
});
});
it('renders search input element', () => {
const inputEl = vm.$el.querySelector('input.dropdown-input-field');
const inputEl = wrapper.find('input.dropdown-input-field');
expect(inputEl).not.toBeNull();
expect(inputEl.getAttribute('placeholder')).toBe('Search');
expect(inputEl.exists()).toBe(true);
expect(inputEl.attributes('placeholder')).toBe('Search');
});
it('renders search input icons', () => {
expect(vm.$el.querySelector('i.fa.fa-search.dropdown-input-search')).not.toBeNull();
expect(vm.$el.querySelector('i.fa.fa-times.dropdown-input-clear')).not.toBeNull();
expect(wrapper.find('i.fa.fa-search.dropdown-input-search').exists()).toBe(true);
expect(wrapper.find('i.fa.fa-times.dropdown-input-clear').exists()).toBe(true);
});
});
});
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import IssueCardWeight from 'ee/boards/components/issue_card_weight.vue';
import mountComponent from 'helpers/vue_mount_component_helper';
describe('IssueCardWeight component', () => {
let vm;
let Component;
beforeAll(() => {
Component = Vue.extend(IssueCardWeight);
function mountIssueCardWeight(propsData) {
return shallowMount(IssueCardWeight, {
propsData,
});
}
describe('IssueCardWeight', () => {
let wrapper;
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
describe('weight text', () => {
it('shows 0 when weight is 0', () => {
wrapper = mountIssueCardWeight({
weight: 0,
});
it('renders weight', () => {
vm = mountComponent(Component, {
expect(wrapper.find('.board-card-info-text').text()).toContain(0);
});
it('shows 5 when weight is 5', () => {
wrapper = mountIssueCardWeight({
weight: 5,
});
expect(vm.$el.querySelector('.board-card-info-text').innerText).toContain('5');
expect(wrapper.find('.board-card-info-text').text()).toContain('5');
});
});
it('renders a link when no tag is specified', () => {
vm = mountComponent(Component, {
wrapper = mountIssueCardWeight({
weight: 2,
});
expect(vm.$el.querySelector('a.board-card-info')).toBeDefined();
expect(wrapper.find('span.board-card-info').exists()).toBe(false);
expect(wrapper.find('a.board-card-info').exists()).toBe(true);
});
it('renders the tag when it is explicitly specified', () => {
vm = mountComponent(Component, {
wrapper = mountIssueCardWeight({
weight: 2,
tagName: 'span',
});
expect(vm.$el.querySelector('span.board-card-info')).toBeDefined();
expect(vm.$el.querySelector('a.board-card-info')).toBeNull();
});
describe('with weight=0', () => {
beforeEach(() => {
vm = mountComponent(Component, {
weight: 0,
});
});
afterEach(() => {
vm.$destroy();
});
it('renders weight', () => {
expect(vm.$el.querySelector('.board-card-info-text')).toBeDefined();
expect(vm.$el.querySelector('.board-card-info-text').innerText).toContain(0);
});
expect(wrapper.find('span.board-card-info').exists()).toBe(true);
expect(wrapper.find('a.board-card-info').exists()).toBe(false);
});
});
import Vue from 'vue';
import mountComponent from 'helpers/vue_mount_component_helper';
import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import IssueCardInnerScopedLabel from '~/boards/components/issue_card_inner_scoped_label.vue';
describe('IssueCardInnerScopedLabel Component', () => {
let vm;
const Component = Vue.extend(IssueCardInnerScopedLabel);
const props = {
let wrapper;
beforeEach(() => {
wrapper = shallowMount(IssueCardInnerScopedLabel, {
propsData: {
label: { title: 'Foo::Bar', description: 'Some Random Description' },
labelStyle: { background: 'white', color: 'black' },
scopedLabelsDocumentationLink: '/docs-link',
};
const createComponent = () => mountComponent(Component, { ...props });
beforeEach(() => {
vm = createComponent();
},
});
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
it('should render label title', () => {
expect(vm.$el.querySelector('.color-label').textContent.trim()).toEqual('Foo::Bar');
expect(wrapper.find('.color-label').text()).toBe('Foo::Bar');
});
it('should render question mark symbol', () => {
expect(vm.$el.querySelector('.fa-question-circle')).not.toBeNull();
expect(wrapper.find('.fa-question-circle').exists()).toBe(true);
});
it('should render label style provided', () => {
const node = vm.$el.querySelector('.color-label');
const label = wrapper.find('.color-label');
expect(node.style.background).toEqual(props.labelStyle.background);
expect(node.style.color).toEqual(props.labelStyle.color);
expect(label.attributes('style')).toContain('background: white;');
expect(label.attributes('style')).toContain('color: black;');
});
it('should render the docs link', () => {
expect(vm.$el.querySelector('a.scoped-label').href).toContain(
props.scopedLabelsDocumentationLink,
);
expect(wrapper.find(GlLink).attributes('href')).toBe('/docs-link');
});
});
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import dateFormat from 'dateformat';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
const createComponent = (dueDate = new Date(), closed = false) =>
shallowMount(IssueDueDate, {
propsData: {
closed,
date: dateFormat(dueDate, 'yyyy-mm-dd', true),
},
});
const findTime = wrapper => wrapper.find('time');
describe('Issue Due Date component', () => {
let vm;
let wrapper;
let date;
const Component = Vue.extend(IssueDueDate);
const createComponent = (dueDate = new Date(), closed = false) =>
mountComponent(Component, { closed, date: dateFormat(dueDate, 'yyyy-mm-dd', true) });
beforeEach(() => {
date = new Date();
vm = createComponent();
});
afterEach(() => {
vm.$destroy();
wrapper.destroy();
});
it('should render "Today" if the due date is today', () => {
const timeContainer = vm.$el.querySelector('time');
wrapper = createComponent();
expect(timeContainer.textContent.trim()).toEqual('Today');
expect(findTime(wrapper).text()).toBe('Today');
});
it('should render "Yesterday" if the due date is yesterday', () => {
date.setDate(date.getDate() - 1);
vm = createComponent(date);
wrapper = createComponent(date);
expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Yesterday');
expect(findTime(wrapper).text()).toBe('Yesterday');
});
it('should render "Tomorrow" if the due date is one day from now', () => {
date.setDate(date.getDate() + 1);
vm = createComponent(date);
wrapper = createComponent(date);
expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Tomorrow');
expect(findTime(wrapper).text()).toBe('Tomorrow');
});
it('should render day of the week if due date is one week away', () => {
date.setDate(date.getDate() + 5);
vm = createComponent(date);
wrapper = createComponent(date);
expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, 'dddd'));
expect(findTime(wrapper).text()).toBe(dateFormat(date, 'dddd'));
});
it('should render month and day for other dates', () => {
date.setDate(date.getDate() + 17);
vm = createComponent(date);
wrapper = createComponent(date);
const today = new Date();
const isDueInCurrentYear = today.getFullYear() === date.getFullYear();
const format = isDueInCurrentYear ? 'mmm d' : 'mmm d, yyyy';
expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, format));
expect(findTime(wrapper).text()).toBe(dateFormat(date, format));
});
it('should contain the correct `.text-danger` css class for overdue issue that is open', () => {
date.setDate(date.getDate() - 17);
vm = createComponent(date);
wrapper = createComponent(date);
expect(vm.$el.querySelector('time').classList.contains('text-danger')).toEqual(true);
expect(findTime(wrapper).classes('text-danger')).toBe(true);
});
it('should not contain the `.text-danger` css class for overdue issue that is closed', () => {
date.setDate(date.getDate() - 17);
vm = createComponent(date, true);
const closed = true;
wrapper = createComponent(date, closed);
expect(vm.$el.querySelector('time').classList.contains('text-danger')).toEqual(false);
expect(findTime(wrapper).classes('text-danger')).toBe(false);
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment