summaryrefslogtreecommitdiff
path: root/spec/javascripts/jobs
diff options
context:
space:
mode:
Diffstat (limited to 'spec/javascripts/jobs')
-rw-r--r--spec/javascripts/jobs/header_spec.js63
-rw-r--r--spec/javascripts/jobs/job_details_mediator_spec.js43
-rw-r--r--spec/javascripts/jobs/job_store_spec.js26
-rw-r--r--spec/javascripts/jobs/mock_data.js123
-rw-r--r--spec/javascripts/jobs/sidebar_detail_row_spec.js40
-rw-r--r--spec/javascripts/jobs/sidebar_details_block_spec.js111
6 files changed, 406 insertions, 0 deletions
diff --git a/spec/javascripts/jobs/header_spec.js b/spec/javascripts/jobs/header_spec.js
new file mode 100644
index 00000000000..c7179b3e03d
--- /dev/null
+++ b/spec/javascripts/jobs/header_spec.js
@@ -0,0 +1,63 @@
+import Vue from 'vue';
+import headerComponent from '~/jobs/components/header.vue';
+
+describe('Job details header', () => {
+ let HeaderComponent;
+ let vm;
+ let props;
+
+ beforeEach(() => {
+ HeaderComponent = Vue.extend(headerComponent);
+
+ const threeWeeksAgo = new Date();
+ threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
+
+ props = {
+ job: {
+ status: {
+ group: 'failed',
+ icon: 'ci-status-failed',
+ label: 'failed',
+ text: 'failed',
+ details_path: 'path',
+ },
+ id: 123,
+ created_at: threeWeeksAgo.toISOString(),
+ user: {
+ web_url: 'path',
+ name: 'Foo',
+ username: 'foobar',
+ email: 'foo@bar.com',
+ avatar_url: 'link',
+ },
+ retry_path: 'path',
+ new_issue_path: 'path',
+ },
+ isLoading: false,
+ };
+
+ vm = new HeaderComponent({ propsData: props }).$mount();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render provided job information', () => {
+ expect(
+ vm.$el.querySelector('.header-main-content').textContent.replace(/\s+/g, ' ').trim(),
+ ).toEqual('failed Job #123 triggered 3 weeks ago by Foo');
+ });
+
+ it('should render retry link', () => {
+ expect(
+ vm.$el.querySelector('.js-retry-button').getAttribute('href'),
+ ).toEqual(props.job.retry_path);
+ });
+
+ it('should render new issue link', () => {
+ expect(
+ vm.$el.querySelector('.js-new-issue').getAttribute('href'),
+ ).toEqual(props.job.new_issue_path);
+ });
+});
diff --git a/spec/javascripts/jobs/job_details_mediator_spec.js b/spec/javascripts/jobs/job_details_mediator_spec.js
new file mode 100644
index 00000000000..1d7fa7e12fc
--- /dev/null
+++ b/spec/javascripts/jobs/job_details_mediator_spec.js
@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import JobMediator from '~/jobs/job_details_mediator';
+import job from './mock_data';
+
+describe('JobMediator', () => {
+ let mediator;
+
+ beforeEach(() => {
+ mediator = new JobMediator({ endpoint: 'foo' });
+ });
+
+ it('should set defaults', () => {
+ expect(mediator.store).toBeDefined();
+ expect(mediator.service).toBeDefined();
+ expect(mediator.options).toEqual({ endpoint: 'foo' });
+ expect(mediator.state.isLoading).toEqual(false);
+ });
+
+ describe('request and store data', () => {
+ const interceptor = (request, next) => {
+ next(request.respondWith(JSON.stringify(job), {
+ status: 200,
+ }));
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(interceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(Vue.http.interceptor, interceptor);
+ });
+
+ it('should store received data', (done) => {
+ mediator.fetchJob();
+
+ setTimeout(() => {
+ expect(mediator.store.state.job).toEqual(job);
+ done();
+ }, 0);
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/job_store_spec.js b/spec/javascripts/jobs/job_store_spec.js
new file mode 100644
index 00000000000..d00faf29d1e
--- /dev/null
+++ b/spec/javascripts/jobs/job_store_spec.js
@@ -0,0 +1,26 @@
+import JobStore from '~/jobs/stores/job_store';
+import job from './mock_data';
+
+describe('Job Store', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new JobStore();
+ });
+
+ it('should set defaults', () => {
+ expect(store.state.job).toEqual({});
+ });
+
+ describe('storeJob', () => {
+ it('should store empty object if none is provided', () => {
+ store.storeJob();
+ expect(store.state.job).toEqual({});
+ });
+
+ it('should store provided argument', () => {
+ store.storeJob(job);
+ expect(store.state.job).toEqual(job);
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js
new file mode 100644
index 00000000000..17e4ef26b2c
--- /dev/null
+++ b/spec/javascripts/jobs/mock_data.js
@@ -0,0 +1,123 @@
+const threeWeeksAgo = new Date();
+threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
+
+export default {
+ id: 4757,
+ name: 'test',
+ build_path: '/root/ci-mock/-/jobs/4757',
+ retry_path: '/root/ci-mock/-/jobs/4757/retry',
+ cancel_path: '/root/ci-mock/-/jobs/4757/cancel',
+ new_issue_path: '/root/ci-mock/issues/new',
+ playable: false,
+ created_at: threeWeeksAgo.toISOString(),
+ updated_at: threeWeeksAgo.toISOString(),
+ finished_at: threeWeeksAgo.toISOString(),
+ queued: 9.54,
+ status: {
+ icon: 'icon_status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ has_details: true,
+ details_path: '/root/ci-mock/-/jobs/4757',
+ favicon: '/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico',
+ action: {
+ icon: 'icon_action_retry',
+ title: 'Retry',
+ path: '/root/ci-mock/-/jobs/4757/retry',
+ method: 'post',
+ },
+ },
+ coverage: 20,
+ erased_at: threeWeeksAgo.toISOString(),
+ duration: 6.785563,
+ tags: ['tag'],
+ user: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ erase_path: '/root/ci-mock/-/jobs/4757/erase',
+ artifacts: [null],
+ runner: {
+ id: 1,
+ description: 'local ci runner',
+ edit_path: '/root/ci-mock/runners/1/edit',
+ },
+ pipeline: {
+ id: 140,
+ user: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ active: false,
+ coverage: null,
+ source: 'unknown',
+ created_at: '2017-05-24T09:59:58.634Z',
+ updated_at: '2017-06-01T17:32:00.062Z',
+ path: '/root/ci-mock/pipelines/140',
+ flags: {
+ latest: true,
+ stuck: false,
+ yaml_errors: false,
+ retryable: false,
+ cancelable: false,
+ },
+ details: {
+ status: {
+ icon: 'icon_status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ has_details: true,
+ details_path: '/root/ci-mock/pipelines/140',
+ favicon: '/assets/ci_favicons/dev/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.ico',
+ },
+ duration: 6,
+ finished_at: '2017-06-01T17:32:00.042Z',
+ },
+ ref: {
+ name: 'abc',
+ path: '/root/ci-mock/commits/abc',
+ tag: false,
+ branch: true,
+ },
+ commit: {
+ id: 'c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ short_id: 'c5864777',
+ title: 'Add new file',
+ created_at: '2017-05-24T10:59:52.000+01:00',
+ parent_ids: ['798e5f902592192afaba73f4668ae30e56eae492'],
+ message: 'Add new file',
+ author_name: 'Root',
+ author_email: 'admin@example.com',
+ authored_date: '2017-05-24T10:59:52.000+01:00',
+ committer_name: 'Root',
+ committer_email: 'admin@example.com',
+ committed_date: '2017-05-24T10:59:52.000+01:00',
+ author: {
+ name: 'Root',
+ username: 'root',
+ id: 1,
+ state: 'active',
+ avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ web_url: 'http://localhost:3000/root',
+ },
+ author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ commit_url: 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ commit_path: '/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ },
+ },
+ merge_request: {
+ iid: 2,
+ path: '/root/ci-mock/merge_requests/2',
+ },
+ raw_path: '/root/ci-mock/builds/4757/raw',
+};
diff --git a/spec/javascripts/jobs/sidebar_detail_row_spec.js b/spec/javascripts/jobs/sidebar_detail_row_spec.js
new file mode 100644
index 00000000000..3ac65709c4a
--- /dev/null
+++ b/spec/javascripts/jobs/sidebar_detail_row_spec.js
@@ -0,0 +1,40 @@
+import Vue from 'vue';
+import sidebarDetailRow from '~/jobs/components/sidebar_detail_row.vue';
+
+describe('Sidebar detail row', () => {
+ let SidebarDetailRow;
+ let vm;
+
+ beforeEach(() => {
+ SidebarDetailRow = Vue.extend(sidebarDetailRow);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render no title', () => {
+ vm = new SidebarDetailRow({
+ propsData: {
+ value: 'this is the value',
+ },
+ }).$mount();
+
+ expect(vm.$el.textContent.replace(/\s+/g, ' ').trim()).toEqual('this is the value');
+ });
+
+ beforeEach(() => {
+ vm = new SidebarDetailRow({
+ propsData: {
+ title: 'this is the title',
+ value: 'this is the value',
+ },
+ }).$mount();
+ });
+
+ it('should render provided title and value', () => {
+ expect(
+ vm.$el.textContent.replace(/\s+/g, ' ').trim(),
+ ).toEqual('this is the title: this is the value');
+ });
+});
diff --git a/spec/javascripts/jobs/sidebar_details_block_spec.js b/spec/javascripts/jobs/sidebar_details_block_spec.js
new file mode 100644
index 00000000000..95532ef5382
--- /dev/null
+++ b/spec/javascripts/jobs/sidebar_details_block_spec.js
@@ -0,0 +1,111 @@
+import Vue from 'vue';
+import sidebarDetailsBlock from '~/jobs/components/sidebar_details_block.vue';
+import job from './mock_data';
+
+describe('Sidebar details block', () => {
+ let SidebarComponent;
+ let vm;
+
+ function trimWhitespace(element) {
+ return element.textContent.replace(/\s+/g, ' ').trim();
+ }
+
+ beforeEach(() => {
+ SidebarComponent = Vue.extend(sidebarDetailsBlock);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('when it is loading', () => {
+ it('should render a loading spinner', () => {
+ vm = new SidebarComponent({
+ propsData: {
+ job: {},
+ isLoading: true,
+ },
+ }).$mount();
+
+ expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
+ });
+ });
+
+ beforeEach(() => {
+ vm = new SidebarComponent({
+ propsData: {
+ job,
+ isLoading: false,
+ },
+ }).$mount();
+ });
+
+ describe('actions', () => {
+ it('should render link to new issue', () => {
+ expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(job.new_issue_path);
+ expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue');
+ });
+
+ it('should render link to retry job', () => {
+ expect(vm.$el.querySelector('.js-retry-job').getAttribute('href')).toEqual(job.retry_path);
+ });
+
+ it('should render link to cancel job', () => {
+ expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
+ });
+ });
+
+ describe('information', () => {
+ it('should render merge request link', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-mr')),
+ ).toEqual('Merge Request: !2');
+
+ expect(
+ vm.$el.querySelector('.js-job-mr a').getAttribute('href'),
+ ).toEqual(job.merge_request.path);
+ });
+
+ it('should render job duration', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-duration')),
+ ).toEqual('Duration: 6 seconds');
+ });
+
+ it('should render erased date', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-erased')),
+ ).toEqual('Erased: 3 weeks ago');
+ });
+
+ it('should render finished date', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-finished')),
+ ).toEqual('Finished: 3 weeks ago');
+ });
+
+ it('should render queued date', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-queued')),
+ ).toEqual('Queued: 9 seconds');
+ });
+
+ it('should render runner ID', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-runner')),
+ ).toEqual('Runner: #1');
+ });
+
+ it('should render coverage', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-coverage')),
+ ).toEqual('Coverage: 20%');
+ });
+
+ it('should render tags', () => {
+ expect(
+ trimWhitespace(vm.$el.querySelector('.js-job-tags')),
+ ).toEqual('Tags: tag');
+ });
+ });
+});