Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-10 12:08:56 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-10 12:08:56 +0300
commitb4ded0ba7b4d2cdbed5b1f331cf2083a25ee4d7c (patch)
tree6694fa9d8f3e226597cc01dfb8e3e07b50ae85b6 /spec/frontend
parent2aaef94c80937d9d188f7b9cbbad2dcd1508c3c1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
-rw-r--r--spec/frontend/blob/components/blob_header_viewer_switcher_spec.js109
-rw-r--r--spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js43
-rw-r--r--spec/frontend/boards/components/issue_due_date_spec.js65
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js29
-rw-r--r--spec/frontend/error_tracking/store/list/mutation_spec.js25
5 files changed, 267 insertions, 4 deletions
diff --git a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
new file mode 100644
index 00000000000..ff0b005f441
--- /dev/null
+++ b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
@@ -0,0 +1,109 @@
+import { mount } from '@vue/test-utils';
+import BlobHeaderViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
+import {
+ RICH_BLOB_VIEWER,
+ RICH_BLOB_VIEWER_TITLE,
+ SIMPLE_BLOB_VIEWER,
+ SIMPLE_BLOB_VIEWER_TITLE,
+} from '~/blob/components/constants';
+import { GlButtonGroup, GlButton } from '@gitlab/ui';
+import { Blob } from './mock_data';
+
+describe('Blob Header Viewer Switcher', () => {
+ let wrapper;
+
+ function createComponent(props = {}) {
+ wrapper = mount(BlobHeaderViewerSwitcher, {
+ propsData: {
+ blob: Object.assign({}, Blob, props),
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('intiialization', () => {
+ it('is initialized with rich viewer as preselected when richViewer exists', () => {
+ createComponent();
+ expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
+ });
+
+ it('is initialized with simple viewer as preselected when richViewer does not exists', () => {
+ createComponent({ richViewer: null });
+ expect(wrapper.vm.viewer).toBe(SIMPLE_BLOB_VIEWER);
+ });
+ });
+
+ describe('rendering', () => {
+ let btnGroup;
+ let buttons;
+
+ beforeEach(() => {
+ createComponent();
+ btnGroup = wrapper.find(GlButtonGroup);
+ buttons = wrapper.findAll(GlButton);
+ });
+
+ it('renders gl-button-group component', () => {
+ expect(btnGroup.exists()).toBe(true);
+ });
+
+ it('renders exactly 2 buttons with predefined actions', () => {
+ expect(buttons.length).toBe(2);
+ [SIMPLE_BLOB_VIEWER_TITLE, RICH_BLOB_VIEWER_TITLE].forEach((title, i) => {
+ expect(buttons.at(i).attributes('title')).toBe(title);
+ });
+ });
+ });
+
+ describe('viewer changes', () => {
+ let buttons;
+ let simpleBtn;
+ let richBtn;
+
+ beforeEach(() => {
+ createComponent();
+ buttons = wrapper.findAll(GlButton);
+ simpleBtn = buttons.at(0);
+ richBtn = buttons.at(1);
+ });
+
+ it('does not switch the viewer if the selected one is already active', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+
+ expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
+ richBtn.vm.$emit('click');
+ expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
+ expect(wrapper.vm.$emit).not.toHaveBeenCalled();
+ });
+
+ it('emits an event when a Simple Viewer button is clicked', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+
+ simpleBtn.vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.viewer).toBe(SIMPLE_BLOB_VIEWER);
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('switch-viewer', SIMPLE_BLOB_VIEWER);
+ });
+ });
+
+ it('emits an event when a Rich Viewer button is clicked', () => {
+ jest.spyOn(wrapper.vm, '$emit');
+
+ wrapper.setData({ viewer: SIMPLE_BLOB_VIEWER });
+
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ richBtn.vm.$emit('click');
+ })
+ .then(() => {
+ expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('switch-viewer', RICH_BLOB_VIEWER);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js b/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js
new file mode 100644
index 00000000000..7389cb14ecb
--- /dev/null
+++ b/spec/frontend/boards/components/issue_card_inner_scoped_label_spec.js
@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import IssueCardInnerScopedLabel from '~/boards/components/issue_card_inner_scoped_label.vue';
+
+describe('IssueCardInnerScopedLabel Component', () => {
+ let vm;
+ const Component = Vue.extend(IssueCardInnerScopedLabel);
+ const props = {
+ 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();
+ });
+
+ it('should render label title', () => {
+ expect(vm.$el.querySelector('.color-label').textContent.trim()).toEqual('Foo::Bar');
+ });
+
+ it('should render question mark symbol', () => {
+ expect(vm.$el.querySelector('.fa-question-circle')).not.toBeNull();
+ });
+
+ it('should render label style provided', () => {
+ const node = vm.$el.querySelector('.color-label');
+
+ expect(node.style.background).toEqual(props.labelStyle.background);
+ expect(node.style.color).toEqual(props.labelStyle.color);
+ });
+
+ it('should render the docs link', () => {
+ expect(vm.$el.querySelector('a.scoped-label').href).toContain(
+ props.scopedLabelsDocumentationLink,
+ );
+ });
+});
diff --git a/spec/frontend/boards/components/issue_due_date_spec.js b/spec/frontend/boards/components/issue_due_date_spec.js
new file mode 100644
index 00000000000..68e26b68f04
--- /dev/null
+++ b/spec/frontend/boards/components/issue_due_date_spec.js
@@ -0,0 +1,65 @@
+import Vue from 'vue';
+import dateFormat from 'dateformat';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('Issue Due Date component', () => {
+ let vm;
+ let date;
+ const Component = Vue.extend(IssueDueDate);
+ const createComponent = (dueDate = new Date()) =>
+ mountComponent(Component, { date: dateFormat(dueDate, 'yyyy-mm-dd', true) });
+
+ beforeEach(() => {
+ date = new Date();
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render "Today" if the due date is today', () => {
+ const timeContainer = vm.$el.querySelector('time');
+
+ expect(timeContainer.textContent.trim()).toEqual('Today');
+ });
+
+ it('should render "Yesterday" if the due date is yesterday', () => {
+ date.setDate(date.getDate() - 1);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Yesterday');
+ });
+
+ it('should render "Tomorrow" if the due date is one day from now', () => {
+ date.setDate(date.getDate() + 1);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Tomorrow');
+ });
+
+ it('should render day of the week if due date is one week away', () => {
+ date.setDate(date.getDate() + 5);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, 'dddd'));
+ });
+
+ it('should render month and day for other dates', () => {
+ date.setDate(date.getDate() + 17);
+ vm = 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));
+ });
+
+ it('should contain the correct `.text-danger` css class for overdue issue', () => {
+ date.setDate(date.getDate() - 17);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').classList.contains('text-danger')).toEqual(true);
+ });
+});
diff --git a/spec/frontend/error_tracking/components/error_tracking_list_spec.js b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
index 9cf73d54d9b..b632b461eb9 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -62,6 +62,7 @@ describe('ErrorTrackingList', () => {
sortByField: jest.fn(),
fetchPaginatedResults: jest.fn(),
updateStatus: jest.fn(),
+ removeIgnoredResolvedErrors: jest.fn(),
};
const state = {
@@ -221,6 +222,8 @@ describe('ErrorTrackingList', () => {
});
describe('When the ignore button on an error is clicked', () => {
+ const ignoreErrorButton = () => wrapper.find({ ref: 'ignoreError' });
+
beforeEach(() => {
store.state.list.loading = false;
store.state.list.errors = errorsList;
@@ -235,20 +238,30 @@ describe('ErrorTrackingList', () => {
});
it('sends the "ignored" status and error ID', () => {
- wrapper.find({ ref: 'ignoreError' }).trigger('click');
+ ignoreErrorButton().trigger('click');
expect(actions.updateStatus).toHaveBeenCalledWith(
expect.anything(),
{
endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
- redirectUrl: '/error_tracking',
status: 'ignored',
},
undefined,
);
});
+
+ it('calls an action to remove the item from the list', () => {
+ ignoreErrorButton().trigger('click');
+ expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(
+ expect.anything(),
+ '1',
+ undefined,
+ );
+ });
});
describe('When the resolve button on an error is clicked', () => {
+ const resolveErrorButton = () => wrapper.find({ ref: 'resolveError' });
+
beforeEach(() => {
store.state.list.loading = false;
store.state.list.errors = errorsList;
@@ -263,17 +276,25 @@ describe('ErrorTrackingList', () => {
});
it('sends "resolved" status and error ID', () => {
- wrapper.find({ ref: 'resolveError' }).trigger('click');
+ resolveErrorButton().trigger('click');
expect(actions.updateStatus).toHaveBeenCalledWith(
expect.anything(),
{
endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
- redirectUrl: '/error_tracking',
status: 'resolved',
},
undefined,
);
});
+
+ it('calls an action to remove the item from the list', () => {
+ resolveErrorButton().trigger('click');
+ expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(
+ expect.anything(),
+ '1',
+ undefined,
+ );
+ });
});
describe('When error tracking is disabled and user is not allowed to enable it', () => {
diff --git a/spec/frontend/error_tracking/store/list/mutation_spec.js b/spec/frontend/error_tracking/store/list/mutation_spec.js
index 44a75b6aa1f..65f11aeeda1 100644
--- a/spec/frontend/error_tracking/store/list/mutation_spec.js
+++ b/spec/frontend/error_tracking/store/list/mutation_spec.js
@@ -5,6 +5,7 @@ import * as types from '~/error_tracking/store/list/mutation_types';
const ADD_RECENT_SEARCH = mutations[types.ADD_RECENT_SEARCH];
const CLEAR_RECENT_SEARCHES = mutations[types.CLEAR_RECENT_SEARCHES];
const LOAD_RECENT_SEARCHES = mutations[types.LOAD_RECENT_SEARCHES];
+const REMOVE_IGNORED_RESOLVED_ERRORS = mutations[types.REMOVE_IGNORED_RESOLVED_ERRORS];
describe('Error tracking mutations', () => {
describe('SET_ERRORS', () => {
@@ -114,5 +115,29 @@ describe('Error tracking mutations', () => {
expect(localStorage.getItem).toHaveBeenCalledWith('recent-searches/project/errors.json');
});
});
+
+ describe('REMOVE_IGNORED_RESOLVED_ERRORS', () => {
+ it('removes ignored or resolved errors from list', () => {
+ state.errors = [
+ {
+ id: 1,
+ status: 'unresolved',
+ },
+ {
+ id: 2,
+ status: 'ignored',
+ },
+ {
+ id: 3,
+ status: 'unresolved',
+ },
+ ];
+ const ignoredError = state.errors[2].id;
+
+ REMOVE_IGNORED_RESOLVED_ERRORS(state, ignoredError);
+
+ expect(state.errors).not.toContain(ignoredError);
+ });
+ });
});
});