summaryrefslogtreecommitdiff
path: root/spec/javascripts
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2018-11-06 15:43:24 +0000
committerDouwe Maan <douwe@gitlab.com>2018-11-06 15:43:24 +0000
commit1208d55206128266690f46f0165df0fc10c24941 (patch)
tree93fbdde5a5db6cdd8f79f2806707dab093985aa2 /spec/javascripts
parentd171ff60168cd55b6d7b9ee920269f44a26e577e (diff)
parentd0c58a97c8a053c0beec7c13c1c6ec5042120ef1 (diff)
downloadgitlab-ce-refactor-snippets-finder.tar.gz
Merge branch 'master' into 'refactor-snippets-finder'refactor-snippets-finder
# Conflicts: # spec/models/project_spec.rb
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/commit/pipelines/pipelines_spec.js23
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js32
-rw-r--r--spec/javascripts/environments/environment_actions_spec.js126
-rw-r--r--spec/javascripts/notes/components/discussion_filter_spec.js24
-rw-r--r--spec/javascripts/notes/components/note_app_spec.js7
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js13
-rw-r--r--spec/javascripts/notes/stores/mutation_spec.js10
-rw-r--r--spec/javascripts/reports/components/grouped_test_reports_app_spec.js4
-rw-r--r--spec/javascripts/reports/components/report_section_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/deployment_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/smart_virtual_list_spec.js83
12 files changed, 276 insertions, 54 deletions
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js
index b797cc44ae7..04c8ab44405 100644
--- a/spec/javascripts/commit/pipelines/pipelines_spec.js
+++ b/spec/javascripts/commit/pipelines/pipelines_spec.js
@@ -72,6 +72,29 @@ describe('Pipelines table in Commits and Merge requests', function() {
done();
}, 0);
});
+
+ describe('with pagination', () => {
+ it('should make an API request when using pagination', done => {
+ setTimeout(() => {
+ spyOn(vm, 'updateContent');
+
+ vm.store.state.pageInfo = {
+ page: 1,
+ total: 10,
+ perPage: 2,
+ nextPage: 2,
+ totalPages: 5,
+ };
+
+ vm.$nextTick(() => {
+ vm.$el.querySelector('.js-next-button a').click();
+
+ expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
+ done();
+ });
+ });
+ });
+ });
});
describe('pipeline badge counts', () => {
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
index b7b29190c31..093fec97951 100644
--- a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
+++ b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
@@ -1,23 +1,35 @@
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import { setInput, createForm } from './helper';
+function expectToToggleDisableOnDirtyUpdate(submit, input) {
+ const originalValue = input.value;
+
+ expect(submit.disabled).toBe(true);
+
+ return setInput(input, `${originalValue} changes`)
+ .then(() => expect(submit.disabled).toBe(false))
+ .then(() => setInput(input, originalValue))
+ .then(() => expect(submit.disabled).toBe(true));
+}
+
describe('DirtySubmitForm', () => {
it('disables submit until there are changes', done => {
const { form, input, submit } = createForm();
- const originalValue = input.value;
new DirtySubmitForm(form); // eslint-disable-line no-new
- expect(submit.disabled).toBe(true);
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('disables submit until there are changes when initializing with a falsy value', done => {
+ const { form, input, submit } = createForm();
+ input.value = '';
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
- return setInput(input, `${originalValue} changes`)
- .then(() => {
- expect(submit.disabled).toBe(false);
- })
- .then(() => setInput(input, originalValue))
- .then(() => {
- expect(submit.disabled).toBe(true);
- })
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
.then(done)
.catch(done.fail);
});
diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js
index 223153d4e31..787df757d32 100644
--- a/spec/javascripts/environments/environment_actions_spec.js
+++ b/spec/javascripts/environments/environment_actions_spec.js
@@ -1,15 +1,19 @@
import Vue from 'vue';
-import actionsComp from '~/environments/components/environment_actions.vue';
+import eventHub from '~/environments/event_hub';
+import EnvironmentActions from '~/environments/components/environment_actions.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'spec/test_constants';
-describe('Actions Component', () => {
- let ActionsComponent;
- let actionsMock;
- let component;
+describe('EnvironmentActions Component', () => {
+ const Component = Vue.extend(EnvironmentActions);
+ let vm;
- beforeEach(() => {
- ActionsComponent = Vue.extend(actionsComp);
+ afterEach(() => {
+ vm.$destroy();
+ });
- actionsMock = [
+ describe('manual actions', () => {
+ const actions = [
{
name: 'bar',
play_path: 'https://gitlab.com/play',
@@ -25,43 +29,89 @@ describe('Actions Component', () => {
},
];
- component = new ActionsComponent({
- propsData: {
- actions: actionsMock,
- },
- }).$mount();
- });
+ beforeEach(() => {
+ vm = mountComponent(Component, { actions });
+ });
+
+ it('should render a dropdown button with icon and title attribute', () => {
+ expect(vm.$el.querySelector('.fa-caret-down')).toBeDefined();
+ expect(vm.$el.querySelector('.dropdown-new').getAttribute('data-original-title')).toEqual(
+ 'Deploy to...',
+ );
- describe('computed', () => {
- it('title', () => {
- expect(component.title).toEqual('Deploy to...');
+ expect(vm.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual(
+ 'Deploy to...',
+ );
});
- });
- it('should render a dropdown button with icon and title attribute', () => {
- expect(component.$el.querySelector('.fa-caret-down')).toBeDefined();
- expect(
- component.$el.querySelector('.dropdown-new').getAttribute('data-original-title'),
- ).toEqual('Deploy to...');
+ it('should render a dropdown with the provided list of actions', () => {
+ expect(vm.$el.querySelectorAll('.dropdown-menu li').length).toEqual(actions.length);
+ });
- expect(component.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual(
- 'Deploy to...',
- );
- });
+ it("should render a disabled action when it's not playable", () => {
+ expect(
+ vm.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
+ ).toEqual('disabled');
- it('should render a dropdown with the provided list of actions', () => {
- expect(component.$el.querySelectorAll('.dropdown-menu li').length).toEqual(actionsMock.length);
+ expect(
+ vm.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
+ ).toEqual(true);
+ });
});
- it("should render a disabled action when it's not playable", () => {
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
- ).toEqual('disabled');
+ describe('scheduled jobs', () => {
+ const scheduledJobAction = {
+ name: 'scheduled action',
+ playPath: `${TEST_HOST}/scheduled/job/action`,
+ playable: true,
+ scheduledAt: '2063-04-05T00:42:00Z',
+ };
+ const expiredJobAction = {
+ name: 'expired action',
+ playPath: `${TEST_HOST}/expired/job/action`,
+ playable: true,
+ scheduledAt: '2018-10-05T08:23:00Z',
+ };
+ const findDropdownItem = action => {
+ const buttons = vm.$el.querySelectorAll('.dropdown-menu li button');
+ return Array.prototype.find.call(buttons, element =>
+ element.innerText.trim().startsWith(action.name),
+ );
+ };
+
+ beforeEach(() => {
+ spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
+ vm = mountComponent(Component, { actions: [scheduledJobAction, expiredJobAction] });
+ });
+
+ it('emits postAction event after confirming', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => true);
+
+ findDropdownItem(scheduledJobAction).click();
+
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).toHaveBeenCalledWith({ endpoint: scheduledJobAction.playPath });
+ });
+
+ it('does not emit postAction event if confirmation is cancelled', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => false);
+
+ findDropdownItem(scheduledJobAction).click();
- expect(
- component.$el
- .querySelector('.dropdown-menu li:last-child button')
- .classList.contains('disabled'),
- ).toEqual(true);
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).not.toHaveBeenCalled();
+ });
+
+ it('displays the remaining time in the dropdown', () => {
+ expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00');
+ });
+
+ it('displays 00:00:00 for expired jobs in the dropdown', () => {
+ expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00');
+ });
});
});
diff --git a/spec/javascripts/notes/components/discussion_filter_spec.js b/spec/javascripts/notes/components/discussion_filter_spec.js
index a81bdf618a3..9070d968cfd 100644
--- a/spec/javascripts/notes/components/discussion_filter_spec.js
+++ b/spec/javascripts/notes/components/discussion_filter_spec.js
@@ -19,7 +19,7 @@ describe('DiscussionFilter component', () => {
},
];
const Component = Vue.extend(DiscussionFilter);
- const defaultValue = discussionFiltersMock[0].value;
+ const selectedValue = discussionFiltersMock[0].value;
store.state.discussions = discussions;
vm = mountComponentWithStore(Component, {
@@ -27,7 +27,7 @@ describe('DiscussionFilter component', () => {
store,
props: {
filters: discussionFiltersMock,
- defaultValue,
+ selectedValue,
},
});
});
@@ -63,4 +63,24 @@ describe('DiscussionFilter component', () => {
expect(vm.filterDiscussion).not.toHaveBeenCalled();
});
+
+ it('disables commenting when "Show history only" filter is applied', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ filterItem.click();
+
+ expect(vm.$store.state.commentsDisabled).toBe(true);
+ });
+
+ it('enables commenting when "Show history only" filter is not applied', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:first-child button');
+ filterItem.click();
+
+ expect(vm.$store.state.commentsDisabled).toBe(false);
+ });
+
+ it('renders a dropdown divider for the default filter', () => {
+ const defaultFilter = vm.$el.querySelector('.dropdown-menu li:first-child');
+
+ expect(defaultFilter.lastChild.classList).toContain('dropdown-divider');
+ });
});
diff --git a/spec/javascripts/notes/components/note_app_spec.js b/spec/javascripts/notes/components/note_app_spec.js
index 3e289a6b8e6..0081f42c330 100644
--- a/spec/javascripts/notes/components/note_app_spec.js
+++ b/spec/javascripts/notes/components/note_app_spec.js
@@ -121,6 +121,13 @@ describe('note_app', () => {
).toEqual('Write a comment or drag your files here…');
});
+ it('should not render form when commenting is disabled', () => {
+ store.state.commentsDisabled = true;
+ vm = mountComponent();
+
+ expect(vm.$el.querySelector('.js-main-target-form')).toEqual(null);
+ });
+
it('should render form comment button as disabled', () => {
expect(vm.$el.querySelector('.js-note-new-discussion').getAttribute('disabled')).toEqual(
'disabled',
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index f4643fd55ed..0c0bc45b201 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -509,4 +509,17 @@ describe('Actions Notes Store', () => {
expect(mrWidgetEventHub.$emit).toHaveBeenCalledWith('mr.discussion.updated');
});
});
+
+ describe('setCommentsDisabled', () => {
+ it('should set comments disabled state', done => {
+ testAction(
+ actions.setCommentsDisabled,
+ true,
+ null,
+ [{ type: 'DISABLE_COMMENTS', payload: true }],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/javascripts/notes/stores/mutation_spec.js b/spec/javascripts/notes/stores/mutation_spec.js
index 380ab59099d..461de5a3106 100644
--- a/spec/javascripts/notes/stores/mutation_spec.js
+++ b/spec/javascripts/notes/stores/mutation_spec.js
@@ -427,4 +427,14 @@ describe('Notes Store mutations', () => {
expect(state.discussions[0].expanded).toBe(true);
});
});
+
+ describe('DISABLE_COMMENTS', () => {
+ it('should set comments disabled state', () => {
+ const state = {};
+
+ mutations.DISABLE_COMMENTS(state, true);
+
+ expect(state.commentsDisabled).toEqual(true);
+ });
+ });
});
diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
index f58515daa4f..69767d9cf1c 100644
--- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
@@ -151,11 +151,11 @@ describe('Grouped Test Reports App', () => {
it('renders resolved failures', done => {
setTimeout(() => {
- expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
+ expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[0].name,
);
- expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
+ expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[1].name,
);
done();
diff --git a/spec/javascripts/reports/components/report_section_spec.js b/spec/javascripts/reports/components/report_section_spec.js
index eb7307605d7..b02af8baaec 100644
--- a/spec/javascripts/reports/components/report_section_spec.js
+++ b/spec/javascripts/reports/components/report_section_spec.js
@@ -120,7 +120,7 @@ describe('Report section', () => {
'Code quality improved on 1 point and degraded on 1 point',
);
- expect(vm.$el.querySelectorAll('.js-mr-code-resolved-issues li').length).toEqual(
+ expect(vm.$el.querySelectorAll('.report-block-container li').length).toEqual(
resolvedIssues.length,
);
});
diff --git a/spec/javascripts/vue_mr_widget/components/deployment_spec.js b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
index 3d44af11153..2f1bd00fa10 100644
--- a/spec/javascripts/vue_mr_widget/components/deployment_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
@@ -242,6 +242,10 @@ describe('Deployment component', () => {
it('renders information about running deployment', () => {
expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain('Deploying to');
});
+
+ it('renders disabled stop button', () => {
+ expect(vm.$el.querySelector('.js-stop-env').getAttribute('disabled')).toBe('disabled');
+ });
});
describe('success', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 6c7637eed13..d905bbe4040 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -73,7 +73,7 @@ describe('MRWidgetPipeline', () => {
});
expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
- 'Could not retrieve the pipeline status. For troubleshooting steps, read the <a href="help">documentation.</a>',
+ 'Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.',
);
});
diff --git a/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
new file mode 100644
index 00000000000..e723fead65e
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
@@ -0,0 +1,83 @@
+import Vue from 'vue';
+import SmartVirtualScrollList from '~/vue_shared/components/smart_virtual_list.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('Toggle Button', () => {
+ let vm;
+
+ const createComponent = ({ length, remain }) => {
+ const smartListProperties = {
+ rtag: 'section',
+ wtag: 'ul',
+ wclass: 'test-class',
+ // Size in pixels does not matter for our tests here
+ size: 35,
+ length,
+ remain,
+ };
+
+ const Component = Vue.extend({
+ components: {
+ SmartVirtualScrollList,
+ },
+ smartListProperties,
+ items: Array(length).fill(1),
+ template: `
+ <smart-virtual-scroll-list v-bind="$options.smartListProperties">
+ <li v-for="(val, key) in $options.items" :key="key">{{ key + 1 }}</li>
+ </smart-virtual-scroll-list>`,
+ });
+
+ return mountComponent(Component);
+ };
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('if the list is shorter than the maximum shown elements', () => {
+ const listLength = 10;
+
+ beforeEach(() => {
+ vm = createComponent({ length: listLength, remain: 20 });
+ });
+
+ it('renders without the vue-virtual-scroll-list component', () => {
+ expect(vm.$el.classList).not.toContain('js-virtual-list');
+ expect(vm.$el.classList).toContain('js-plain-element');
+ });
+
+ it('renders list with provided tags and classes for the wrapper elements', () => {
+ expect(vm.$el.tagName).toEqual('SECTION');
+ expect(vm.$el.firstChild.tagName).toEqual('UL');
+ expect(vm.$el.firstChild.classList).toContain('test-class');
+ });
+
+ it('renders all children list elements', () => {
+ expect(vm.$el.querySelectorAll('li').length).toEqual(listLength);
+ });
+ });
+
+ describe('if the list is longer than the maximum shown elements', () => {
+ const maxItemsShown = 20;
+
+ beforeEach(() => {
+ vm = createComponent({ length: 1000, remain: maxItemsShown });
+ });
+
+ it('uses the vue-virtual-scroll-list component', () => {
+ expect(vm.$el.classList).toContain('js-virtual-list');
+ expect(vm.$el.classList).not.toContain('js-plain-element');
+ });
+
+ it('renders list with provided tags and classes for the wrapper elements', () => {
+ expect(vm.$el.tagName).toEqual('SECTION');
+ expect(vm.$el.firstChild.tagName).toEqual('UL');
+ expect(vm.$el.firstChild.classList).toContain('test-class');
+ });
+
+ it('renders at max twice the maximum shown elements', () => {
+ expect(vm.$el.querySelectorAll('li').length).toBeLessThanOrEqual(2 * maxItemsShown);
+ });
+ });
+});