summaryrefslogtreecommitdiff
path: root/spec/javascripts
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-10-05 16:30:33 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2018-10-05 16:30:33 +0000
commit059da9bc8eb9355a760031ef8e73b0aa6285012f (patch)
treeb6057c99d0c53951a650122d624dc37405194551 /spec/javascripts
parent7f86172f806558d2b614abcb06cef0ea516c5900 (diff)
parent7542a5d102bc48f5f7b8104fda22f0975b2dd931 (diff)
downloadgitlab-ce-059da9bc8eb9355a760031ef8e73b0aa6285012f.tar.gz
Merge branch 'scheduled-manual-jobs' into 'master'
Delayed jobs Closes #51352 See merge request gitlab-org/gitlab-ce!21767
Diffstat (limited to 'spec/javascripts')
-rw-r--r--spec/javascripts/datetime_utility_spec.js25
-rw-r--r--spec/javascripts/pipelines/pipelines_actions_spec.js104
-rw-r--r--spec/javascripts/pipelines/pipelines_table_row_spec.js7
3 files changed, 104 insertions, 32 deletions
diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js
index 492171684dc..6c3e73f134e 100644
--- a/spec/javascripts/datetime_utility_spec.js
+++ b/spec/javascripts/datetime_utility_spec.js
@@ -6,9 +6,7 @@ describe('Date time utils', () => {
const date = new Date();
date.setFullYear(date.getFullYear() - 1);
- expect(
- datetimeUtility.timeFor(date),
- ).toBe('Past due');
+ expect(datetimeUtility.timeFor(date)).toBe('Past due');
});
it('returns remaining time when in the future', () => {
@@ -19,9 +17,7 @@ describe('Date time utils', () => {
// short of a full year, timeFor will return '11 months remaining'
date.setDate(date.getDate() + 1);
- expect(
- datetimeUtility.timeFor(date),
- ).toBe('1 year remaining');
+ expect(datetimeUtility.timeFor(date)).toBe('1 year remaining');
});
});
@@ -168,3 +164,20 @@ describe('getTimeframeWindowFrom', () => {
});
});
});
+
+describe('formatTime', () => {
+ const expectedTimestamps = [
+ [0, '00:00:00'],
+ [1000, '00:00:01'],
+ [42000, '00:00:42'],
+ [121000, '00:02:01'],
+ [10921000, '03:02:01'],
+ [108000000, '30:00:00'],
+ ];
+
+ expectedTimestamps.forEach(([milliseconds, expectedTimestamp]) => {
+ it(`formats ${milliseconds}ms as ${expectedTimestamp}`, () => {
+ expect(datetimeUtility.formatTime(milliseconds)).toBe(expectedTimestamp);
+ });
+ });
+});
diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js
index 72fb0a8f9ef..0566bc55693 100644
--- a/spec/javascripts/pipelines/pipelines_actions_spec.js
+++ b/spec/javascripts/pipelines/pipelines_actions_spec.js
@@ -1,46 +1,98 @@
import Vue from 'vue';
-import pipelinesActionsComp from '~/pipelines/components/pipelines_actions.vue';
+import eventHub from '~/pipelines/event_hub';
+import PipelinesActions from '~/pipelines/components/pipelines_actions.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'spec/test_constants';
describe('Pipelines Actions dropdown', () => {
- let component;
- let actions;
- let ActionsComponent;
+ const Component = Vue.extend(PipelinesActions);
+ let vm;
- beforeEach(() => {
- ActionsComponent = Vue.extend(pipelinesActionsComp);
+ afterEach(() => {
+ vm.$destroy();
+ });
- actions = [
+ describe('manual actions', () => {
+ const actions = [
{
name: 'stop_review',
- path: '/root/review-app/builds/1893/play',
+ path: `${TEST_HOST}/root/review-app/builds/1893/play`,
},
{
name: 'foo',
- path: '#',
+ path: `${TEST_HOST}/disabled/pipeline/action`,
playable: false,
},
];
- component = new ActionsComponent({
- propsData: {
- actions,
- },
- }).$mount();
- });
+ beforeEach(() => {
+ vm = mountComponent(Component, { actions });
+ });
- it('should render a dropdown with the provided actions', () => {
- expect(
- component.$el.querySelectorAll('.dropdown-menu li').length,
- ).toEqual(actions.length);
+ it('renders a dropdown with the provided actions', () => {
+ const dropdownItems = vm.$el.querySelectorAll('.dropdown-menu li');
+ expect(dropdownItems.length).toEqual(actions.length);
+ });
+
+ it("renders a disabled action when it's not playable", () => {
+ const dropdownItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ expect(dropdownItem).toBeDisabled();
+ });
});
- 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',
+ path: `${TEST_HOST}/scheduled/job/action`,
+ playable: true,
+ scheduled_at: '2063-04-05T00:42:00Z',
+ };
+ const expiredJobAction = {
+ name: 'expired action',
+ path: `${TEST_HOST}/expired/job/action`,
+ playable: true,
+ scheduled_at: '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(scheduledJobAction.path);
+ });
+
+ 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(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).not.toHaveBeenCalled();
+ });
+
+ it('displays the remaining time in the dropdown', () => {
+ expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00');
+ });
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
- ).toEqual(true);
+ it('displays 00:00:00 for expired jobs in the dropdown', () => {
+ expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00');
+ });
});
});
diff --git a/spec/javascripts/pipelines/pipelines_table_row_spec.js b/spec/javascripts/pipelines/pipelines_table_row_spec.js
index 03ffc122795..42795f5c134 100644
--- a/spec/javascripts/pipelines/pipelines_table_row_spec.js
+++ b/spec/javascripts/pipelines/pipelines_table_row_spec.js
@@ -158,8 +158,13 @@ describe('Pipelines Table Row', () => {
});
describe('actions column', () => {
+ const scheduledJobAction = {
+ name: 'some scheduled job',
+ };
+
beforeEach(() => {
const withActions = Object.assign({}, pipeline);
+ withActions.details.scheduled_actions = [scheduledJobAction];
withActions.flags.cancelable = true;
withActions.flags.retryable = true;
withActions.cancel_path = '/cancel';
@@ -171,6 +176,8 @@ describe('Pipelines Table Row', () => {
it('should render the provided actions', () => {
expect(component.$el.querySelector('.js-pipelines-retry-button')).not.toBeNull();
expect(component.$el.querySelector('.js-pipelines-cancel-button')).not.toBeNull();
+ const dropdownMenu = component.$el.querySelectorAll('.dropdown-menu');
+ expect(dropdownMenu).toContainText(scheduledJobAction.name);
});
it('emits `retryPipeline` event when retry button is clicked and toggles loading', () => {