summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb72
-rw-r--r--spec/features/projects/files/user_deletes_files_spec.rb2
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb22
-rw-r--r--spec/javascripts/job_spec.js560
-rw-r--r--spec/javascripts/jobs/components/job_app_spec.js645
-rw-r--r--spec/javascripts/jobs/components/job_log_spec.js37
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js17
-rw-r--r--spec/javascripts/jobs/mock_data.js2
-rw-r--r--spec/javascripts/jobs/store/actions_spec.js188
-rw-r--r--spec/javascripts/jobs/store/helpers.js6
-rw-r--r--spec/javascripts/jobs/store/mutations_spec.js55
-rw-r--r--spec/javascripts/pipelines/graph/job_group_dropdown_spec.js (renamed from spec/javascripts/pipelines/graph/dropdown_job_component_spec.js)18
-rw-r--r--spec/javascripts/pipelines/graph/job_item_spec.js (renamed from spec/javascripts/pipelines/graph/job_component_spec.js)6
-rw-r--r--spec/javascripts/pipelines/graph/stage_column_component_spec.js17
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js2
17 files changed, 898 insertions, 755 deletions
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 32cd7c6e70a..28f7e4634a5 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -343,4 +343,76 @@ describe Projects::BlobController do
end
end
end
+
+ describe 'DELETE destroy' do
+ let(:user) { create(:user) }
+ let(:project_root_path) { project_tree_path(project, 'master') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'for a file in a subdirectory' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'master/files/whitespace',
+ original_branch: 'master',
+ branch_name: 'master',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ let(:after_delete_path) { project_tree_path(project, 'master/files') }
+
+ it 'redirects to the sub directory' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(after_delete_path)
+ end
+ end
+
+ context 'if deleted file is the last one in a subdirectory' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'master/bar/branch-test.txt',
+ original_branch: 'master',
+ branch_name: 'master',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ it 'redirects to the project root' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(project_root_path)
+ end
+
+ context 'when deleting a file in a branch other than master' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'binary-encoding/foo/bar/.gitkeep',
+ original_branch: 'binary-encoding',
+ branch_name: 'binary-encoding',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ let(:after_delete_path) { project_tree_path(project, 'binary-encoding') }
+
+ it 'redirects to the project root of the branch' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(after_delete_path)
+ end
+ end
+ end
+ end
end
diff --git a/spec/features/projects/files/user_deletes_files_spec.rb b/spec/features/projects/files/user_deletes_files_spec.rb
index dcb7b947c61..614b11fa5c8 100644
--- a/spec/features/projects/files/user_deletes_files_spec.rb
+++ b/spec/features/projects/files/user_deletes_files_spec.rb
@@ -31,7 +31,7 @@ describe 'Projects > Files > User deletes files', :js do
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Delete file')
- expect(current_path).to eq(project_tree_path(project, 'master'))
+ expect(current_path).to eq(project_tree_path(project, 'master/'))
expect(page).not_to have_content('.gitignore')
end
end
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index e639f0cf82e..6ce37297a7e 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -67,7 +67,7 @@ describe 'Project Jobs Permissions' do
it_behaves_like 'recent job page details responds with status', 200 do
it 'renders job details', :js do
expect(page).to have_content "Job ##{job.id}"
- expect(page).to have_css '#build-trace'
+ expect(page).to have_css '.js-build-trace'
end
end
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index fc7b78ac21f..908c616f2fc 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -20,7 +20,7 @@ describe 'User browses a job', :js do
wait_for_requests
expect(page).to have_content("Job ##{build.id}")
- expect(page).to have_css('#build-trace')
+ expect(page).to have_css('.js-build-trace')
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index a3a301504ff..7f5c3ff6ed8 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -294,7 +294,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- describe 'Raw trace' do
+ describe 'Raw trace', :js do
before do
job.run!
@@ -302,7 +302,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it do
- expect(page).to have_css('.js-raw-link')
+ wait_for_all_requests
+ expect(page).to have_css('.js-raw-link-controller')
end
end
@@ -636,7 +637,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'Canceled job' do
+ context 'Canceled job', :js do
context 'with log' do
let(:job) { create(:ci_build, :canceled, :trace_artifact, pipeline: pipeline) }
@@ -645,7 +646,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'renders job log' do
- expect(page).to have_selector('.js-build-output')
+ wait_for_all_requests
+ expect(page).to have_selector('.js-build-trace')
end
end
@@ -658,7 +660,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
- expect(page).not_to have_selector('.js-build-output')
+ expect(page).not_to have_selector('.js-build-trace')
expect(page).to have_content('This job has been canceled')
end
end
@@ -673,7 +675,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
- expect(page).not_to have_selector('.js-build-output')
+ expect(page).not_to have_selector('.js-build-trace')
expect(page).to have_content('This job has been skipped')
end
end
@@ -722,8 +724,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
wait_for_requests
- expect(page).to have_css('.js-build-sidebar.right-sidebar-collapsed', visible: false)
- expect(page).not_to have_css('.js-build-sidebar.right-sidebar-expanded', visible: false)
+ expect(page).to have_css('.js-job-sidebar.right-sidebar-collapsed', visible: false)
+ expect(page).not_to have_css('.js-job-sidebar.right-sidebar-expanded', visible: false)
end
end
@@ -734,8 +736,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
wait_for_requests
- expect(page).to have_css('.js-build-sidebar.right-sidebar-expanded')
- expect(page).not_to have_css('.js-build-sidebar.right-sidebar-collpased')
+ expect(page).to have_css('.js-job-sidebar.right-sidebar-expanded')
+ expect(page).not_to have_css('.js-job-sidebar.right-sidebar-collpased')
end
end
end
diff --git a/spec/javascripts/job_spec.js b/spec/javascripts/job_spec.js
index d6b5dec9e47..bc973407b25 100644
--- a/spec/javascripts/job_spec.js
+++ b/spec/javascripts/job_spec.js
@@ -1,295 +1,265 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import '~/lib/utils/datetime_utility';
-import Job from '~/job';
-import '~/breakpoints';
-import waitForPromises from 'spec/helpers/wait_for_promises';
-
-describe('Job', () => {
- const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`;
- let mock;
- let response;
- let job;
-
- preloadFixtures('builds/build-with-artifacts.html.raw');
-
- beforeEach(() => {
- loadFixtures('builds/build-with-artifacts.html.raw');
-
- spyOnDependency(Job, 'visitUrl');
-
- response = {};
-
- mock = new MockAdapter(axios);
-
- mock.onGet(new RegExp(`${JOB_URL}/trace.json?(.*)`)).reply(() => [200, response]);
- });
-
- afterEach(() => {
- mock.restore();
-
- clearTimeout(job.timeout);
- });
-
- describe('class constructor', () => {
- beforeEach(() => {
- jasmine.clock().install();
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- describe('setup', () => {
- beforeEach(function (done) {
- job = new Job();
-
- waitForPromises()
- .then(done)
- .catch(done.fail);
- });
-
- it('copies build options', function () {
- expect(job.pagePath).toBe(JOB_URL);
- expect(job.buildStatus).toBe('success');
- expect(job.buildStage).toBe('test');
- expect(job.state).toBe('');
- });
- });
-
- describe('running build', () => {
- it('updates the build trace on an interval', function (done) {
- response = {
- html: '<span>Update<span>',
- status: 'running',
- state: 'newstate',
- append: true,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
- expect(job.state).toBe('newstate');
-
- response = {
- html: '<span>More</span>',
- status: 'running',
- state: 'finalstate',
- append: true,
- complete: true,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/);
- expect(job.state).toBe('finalstate');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('replaces the entire build trace', (done) => {
- response = {
- html: '<span>Update<span>',
- status: 'running',
- append: false,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
-
- response = {
- html: '<span>Different</span>',
- status: 'running',
- append: false,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/);
- expect($('#build-trace .js-build-output').text()).toMatch(/Different/);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('truncated information', () => {
- describe('when size is less than total', () => {
- it('shows information about truncated log', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows the size in KiB', (done) => {
- const size = 50;
-
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(size)}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows incremented size', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(50)}`);
-
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: true,
- size: 10,
- total: 100,
- complete: true,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(60)}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders the raw link', () => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- expect(
- document.querySelector('.js-raw-link').textContent.trim(),
- ).toContain('Complete Raw');
- });
- });
-
- describe('when size is equal than total', () => {
- it('does not show the trunctated information', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 100,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(document.querySelector('.js-truncated-info').classList).toContain('hidden');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('output trace', () => {
- beforeEach((done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(done)
- .catch(done.fail);
- });
-
- it('should render trace controls', () => {
- const controllers = document.querySelector('.controllers');
-
- expect(controllers.querySelector('.js-raw-link-controller')).not.toBeNull();
- expect(controllers.querySelector('.js-scroll-up')).not.toBeNull();
- expect(controllers.querySelector('.js-scroll-down')).not.toBeNull();
- });
-
- it('should render received output', () => {
- expect(
- document.querySelector('.js-build-output').innerHTML,
- ).toEqual('<span>Update</span>');
- });
- });
- });
-
- describe('getBuildTrace', () => {
- it('should request build trace with state parameter', (done) => {
- spyOn(axios, 'get').and.callThrough();
- job = new Job();
-
- setTimeout(() => {
- expect(axios.get).toHaveBeenCalledWith(
- `${JOB_URL}/trace.json`, { params: { state: '' } },
- );
- done();
- }, 0);
- });
- });
-});
+// import $ from 'jquery';
+// import MockAdapter from 'axios-mock-adapter';
+// import axios from '~/lib/utils/axios_utils';
+// import { numberToHumanSize } from '~/lib/utils/number_utils';
+// import '~/lib/utils/datetime_utility';
+// import Job from '~/job';
+// import '~/breakpoints';
+// import waitForPromises from 'spec/helpers/wait_for_promises';
+
+// describe('Job', () => {
+// const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`;
+// let mock;
+// let response;
+// let job;
+
+// preloadFixtures('builds/build-with-artifacts.html.raw');
+
+// beforeEach(() => {
+// loadFixtures('builds/build-with-artifacts.html.raw');
+
+// spyOnDependency(Job, 'visitUrl');
+
+// response = {};
+
+// mock = new MockAdapter(axios);
+
+// mock.onGet(new RegExp(`${JOB_URL}/trace.json?(.*)`)).reply(() => [200, response]);
+// });
+
+// afterEach(() => {
+// mock.restore();
+
+// clearTimeout(job.timeout);
+// });
+
+// describe('class constructor', () => {
+// beforeEach(() => {
+// jasmine.clock().install();
+// });
+
+// afterEach(() => {
+// jasmine.clock().uninstall();
+// });
+
+// describe('running build', () => {
+// it('updates the build trace on an interval', function (done) {
+// response = {
+// html: '<span>Update<span>',
+// status: 'running',
+// state: 'newstate',
+// append: true,
+// complete: false,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
+// expect(job.state).toBe('newstate');
+
+// response = {
+// html: '<span>More</span>',
+// status: 'running',
+// state: 'finalstate',
+// append: true,
+// complete: true,
+// };
+// })
+// .then(() => jasmine.clock().tick(4001))
+// .then(waitForPromises)
+// .then(() => {
+// expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/);
+// expect(job.state).toBe('finalstate');
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+
+// it('replaces the entire build trace', (done) => {
+// response = {
+// html: '<span>Update<span>',
+// status: 'running',
+// append: false,
+// complete: false,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
+
+// response = {
+// html: '<span>Different</span>',
+// status: 'running',
+// append: false,
+// };
+// })
+// .then(() => jasmine.clock().tick(4001))
+// .then(waitForPromises)
+// .then(() => {
+// expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/);
+// expect($('#build-trace .js-build-output').text()).toMatch(/Different/);
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+// });
+
+// describe('truncated information', () => {
+// describe('when size is less than total', () => {
+// it('shows information about truncated log', (done) => {
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size: 50,
+// total: 100,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden');
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+
+// it('shows the size in KiB', (done) => {
+// const size = 50;
+
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size,
+// total: 100,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect(
+// document.querySelector('.js-truncated-info-size').textContent.trim(),
+// ).toEqual(`${numberToHumanSize(size)}`);
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+
+// it('shows incremented size', (done) => {
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size: 50,
+// total: 100,
+// complete: false,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect(
+// document.querySelector('.js-truncated-info-size').textContent.trim(),
+// ).toEqual(`${numberToHumanSize(50)}`);
+
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: true,
+// size: 10,
+// total: 100,
+// complete: true,
+// };
+// })
+// .then(() => jasmine.clock().tick(4001))
+// .then(waitForPromises)
+// .then(() => {
+// expect(
+// document.querySelector('.js-truncated-info-size').textContent.trim(),
+// ).toEqual(`${numberToHumanSize(60)}`);
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+
+// it('renders the raw link', () => {
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size: 50,
+// total: 100,
+// };
+
+// job = new Job();
+
+// expect(
+// document.querySelector('.js-raw-link').textContent.trim(),
+// ).toContain('Complete Raw');
+// });
+// });
+
+// describe('when size is equal than total', () => {
+// it('does not show the trunctated information', (done) => {
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size: 100,
+// total: 100,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(() => {
+// expect(document.querySelector('.js-truncated-info').classList).toContain('hidden');
+// })
+// .then(done)
+// .catch(done.fail);
+// });
+// });
+// });
+
+// describe('output trace', () => {
+// beforeEach((done) => {
+// response = {
+// html: '<span>Update</span>',
+// status: 'success',
+// append: false,
+// size: 50,
+// total: 100,
+// };
+
+// job = new Job();
+
+// waitForPromises()
+// .then(done)
+// .catch(done.fail);
+// });
+
+// it('should render trace controls', () => {
+// const controllers = document.querySelector('.controllers');
+
+// expect(controllers.querySelector('.js-raw-link-controller')).not.toBeNull();
+// expect(controllers.querySelector('.js-scroll-up')).not.toBeNull();
+// expect(controllers.querySelector('.js-scroll-down')).not.toBeNull();
+// });
+
+// it('should render received output', () => {
+// expect(
+// document.querySelector('.js-build-output').innerHTML,
+// ).toEqual('<span>Update</span>');
+// });
+// });
+// });
+
+// });
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
index 6e0bcf801cd..e6d403dc826 100644
--- a/spec/javascripts/jobs/components/job_app_spec.js
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -1,75 +1,196 @@
import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
import jobApp from '~/jobs/components/job_app.vue';
import createStore from '~/jobs/store';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { resetStore } from '../store/helpers';
+import job from '../mock_data';
describe('Job App ', () => {
const Component = Vue.extend(jobApp);
let store;
let vm;
-
- const threeWeeksAgo = new Date();
- threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-
- const twoDaysAgo = new Date();
- twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
-
- const job = {
- status: {
- group: 'failed',
- icon: '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',
- },
- started: twoDaysAgo.toISOString(),
- new_issue_path: 'path',
- runners: {
- available: false,
- },
- tags: ['docker'],
- has_trace: true,
- };
+ let mock;
const props = {
+ endpoint: `${gl.TEST_HOST}jobs/123.json`,
+ runnerHelpUrl: 'help/runner',
runnerSettingsUrl: 'settings/ci-cd/runners',
+ terminalPath: 'jobs/123/terminal',
+ pagePath: `${gl.TEST_HOST}jobs/123`,
+ logState:
+ 'eyJvZmZzZXQiOjE3NDUxLCJuX29wZW5fdGFncyI6MCwiZmdfY29sb3IiOm51bGwsImJnX2NvbG9yIjpudWxsLCJzdHlsZV9tYXNrIjowfQ%3D%3D',
};
beforeEach(() => {
+ mock = new MockAdapter(axios);
store = createStore();
});
afterEach(() => {
+ resetStore(store);
vm.$destroy();
+ mock.restore();
});
- describe('Header section', () => {
- describe('job callout message', () => {
- it('should not render the reason when reason is absent', () => {
- store.dispatch('receiveJobSuccess', job);
+ describe('while loading', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, job, {});
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {});
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('renders loading icon', done => {
+ expect(vm.$el.querySelector('.js-job-loading')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-job-sidebar')).toBeNull();
+ expect(vm.$el.querySelector('.js-job-content')).toBeNull();
+
+ setTimeout(() => {
+ done();
+ }, 0);
+ });
+ });
+
+ describe('with successfull request', () => {
+ beforeEach(() => {
+ mock.onGet(`${props.pagePath}/trace.json`).replyOnce(200, {});
+ });
+
+ describe('Header section', () => {
+ describe('job callout message', () => {
+ it('should not render the reason when reason is absent', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(vm.shouldRenderCalloutMessage).toBe(false);
+
+ done();
+ }, 0);
+ });
+
+ it('should render the reason when reason is present', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ callout_message: 'There is an unknown failure, please try again',
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, { props, store });
+ setTimeout(() => {
+ expect(vm.shouldRenderCalloutMessage).toBe(true);
+ done();
+ }, 0);
+ });
+ });
+
+ describe('triggered job', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { started: '2017-05-24T10:59:52.000+01:00' }));
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('should render provided job information', done => {
+ setTimeout(() => {
+ expect(
+ vm.$el
+ .querySelector('.header-main-content')
+ .textContent.replace(/\s+/g, ' ')
+ .trim(),
+ ).toEqual('passed Job #4757 triggered 1 year ago by Root');
+ done();
+ }, 0);
+ });
+
+ it('should render new issue link', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
+ job.new_issue_path,
+ );
+ done();
+ }, 0);
+ });
+ });
+
+ describe('created job', () => {
+ it('should render created key', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(
+ vm.$el
+ .querySelector('.header-main-content')
+ .textContent.replace(/\s+/g, ' ')
+ .trim(),
+ ).toEqual('passed Job #4757 created 3 weeks ago by Root');
+ done();
+ }, 0);
+ });
+ });
+ });
+
+ describe('stuck block', () => {
+ it('renders stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ },
+ runners: {
+ available: false,
+ },
+ }),
+ );
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('renders tags in stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ },
+ runners: {
+ available: false,
+ },
+ }),
+ );
vm = mountComponentWithStore(Component, {
props,
store,
});
- expect(vm.shouldRenderCalloutMessage).toBe(false);
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]);
+ done();
+ }, 0);
});
- it('should render the reason when reason is present', () => {
- store.dispatch(
- 'receiveJobSuccess',
+ it('does not renders stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
Object.assign({}, job, {
- callout_message: 'There is an unknown failure, please try again',
+ runners: { available: true },
}),
);
@@ -78,246 +199,324 @@ describe('Job App ', () => {
store,
});
- expect(vm.shouldRenderCalloutMessage).toBe(true);
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck')).toBeNull();
+
+ done();
+ }, 0);
});
});
- describe('triggered job', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
+ describe('environments block', () => {
+ it('renders environment block when job has environment', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ deployment_status: {
+ environment: {
+ environment_path: '/path',
+ name: 'foo',
+ },
+ },
+ }),
+ );
vm = mountComponentWithStore(Component, {
props,
store,
});
- });
- it('should render provided job information', () => {
- expect(
- vm.$el
- .querySelector('.header-main-content')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toEqual('failed Job #123 triggered 2 days ago by Foo');
- });
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-environment')).not.toBeNull();
- it('should render new issue link', () => {
- expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
- job.new_issue_path,
- );
+ done();
+ }, 0);
});
- });
- describe('created job', () => {
- it('should render created key', () => {
- store.dispatch('receiveJobSuccess', Object.assign({}, job, { started: false }));
+ it('does not render environment block when job has environment', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
vm = mountComponentWithStore(Component, {
props,
store,
});
- expect(
- vm.$el
- .querySelector('.header-main-content')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toEqual('failed Job #123 created 3 weeks ago by Foo');
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-environment')).toBeNull();
+ done();
+ }, 0);
});
});
- });
- describe('stuck block', () => {
- it('renders stuck block when there are no runners', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- },
- }),
- );
-
- vm = mountComponentWithStore(Component, {
- props,
- store,
- });
+ describe('erased block', () => {
+ it('renders erased block when `erased` is true', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ erased_by: {
+ username: 'root',
+ web_url: 'gitlab.com/root',
+ },
+ erased_at: '2016-11-07T11:11:16.525Z',
+ }),
+ );
- expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull();
- });
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
- it('renders tags in stuck block when there are no runners', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- },
- }),
- );
-
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-erased-block')).not.toBeNull();
+
+ done();
+ }, 0);
});
- expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]);
- });
+ it('does not render erased block when `erased` is false', done => {
+ mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { erased_at: null }));
- it(' does not renders stuck block when there are no runners', () => {
- store.dispatch('receiveJobSuccess', Object.assign({}, job, { runners: { available: true } }));
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
- vm = mountComponentWithStore(Component, {
- props,
- store,
- });
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-erased-block')).toBeNull();
- expect(vm.$el.querySelector('.js-job-stuck')).toBeNull();
+ done();
+ }, 0);
+ });
});
- });
- describe('environments block', () => {
- it('renders environment block when job has environment', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- deployment_status: {
- environment: {
- environment_path: '/path',
- name: 'foo',
+ describe('empty states block', () => {
+ it('renders empty state when job does not have trace and is not running', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ illustration: {
+ image: 'path',
+ size: '340',
+ title: 'Empty State',
+ content: 'This is an empty state',
+ },
+ action: {
+ button_title: 'Retry job',
+ method: 'post',
+ path: '/path',
+ },
},
- },
- }),
- );
+ }),
+ );
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull();
+
+ done();
+ }, 0);
});
- expect(vm.$el.querySelector('.js-job-environment')).not.toBeNull();
- });
+ it('does not render empty state when job does not have trace but it is running', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'running',
+ icon: 'status_running',
+ label: 'running',
+ text: 'running',
+ details_path: 'path',
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
- it('does not render environment block when job has environment', () => {
- store.dispatch('receiveJobSuccess', job);
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ done();
+ }, 0);
});
- expect(vm.$el.querySelector('.js-job-environment')).toBeNull();
- });
- });
+ it('does not render empty state when job has trace but it is not running', done => {
+ mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { has_trace: true }));
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
- describe('erased block', () => {
- it('renders erased block when `erased` is true', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- erased_by: {
- username: 'root',
- web_url: 'gitlab.com/root',
- },
- erased_at: '2016-11-07T11:11:16.525Z',
- }),
- );
-
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+
+ done();
+ }, 0);
});
+ });
+ });
- expect(vm.$el.querySelector('.js-job-erased-block')).not.toBeNull();
+ describe('trace output', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, job, {});
});
- it('does not render erased block when `erased` is false', () => {
- store.dispatch('receiveJobSuccess', Object.assign({}, job, { erased_at: null }));
+ describe('with append flag', () => {
+ it('appends the log content to the existing one', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>More<span>',
+ status: 'running',
+ state: 'newstate',
+ append: true,
+ complete: true,
+ });
- vm = mountComponentWithStore(Component, {
- props,
- store,
- });
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
- expect(vm.$el.querySelector('.js-job-erased-block')).toBeNull();
- });
- });
+ vm.$store.state.trace = 'Update';
- describe('empty states block', () => {
- it('renders empty state when job does not have trace and is not running', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- has_trace: false,
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- illustration: {
- image: 'path',
- size: '340',
- title: 'Empty State',
- content: 'This is an empty state',
- },
- action: {
- button_title: 'Retry job',
- method: 'post',
- path: '/path',
- },
- },
- }),
- );
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain('Update');
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ done();
+ }, 0);
});
+ });
+
+ describe('without append flag', () => {
+ it('replaces the trace', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Different<span>',
+ status: 'running',
+ append: false,
+ complete: true,
+ });
- expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull();
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ vm.$store.state.trace = 'Update';
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).not.toContain('Update');
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain(
+ 'Different',
+ );
+ done();
+ }, 0);
+ });
});
- it('does not render empty state when job does not have trace but it is running', () => {
- store.dispatch(
- 'receiveJobSuccess',
- Object.assign({}, job, {
- has_trace: false,
- status: {
- group: 'running',
- icon: 'status_running',
- label: 'running',
- text: 'running',
- details_path: 'path',
- },
- }),
- );
-
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ describe('truncated information', () => {
+ describe('when size is less than total', () => {
+ it('shows information about truncated log', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 50,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).toContain(
+ '50 bytes',
+ );
+ done();
+ }, 0);
+ });
});
- expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+ describe('when size is equal than total', () => {
+ it('does not show the truncated information', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 100,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).not.toContain(
+ '50 bytes',
+ );
+ done();
+ }, 0);
+ });
+ });
});
- it('does not render empty state when job has trace but it is not running', () => {
- store.dispatch('receiveJobSuccess', Object.assign({}, job, { has_trace: true }));
+ describe('trace controls', () => {
+ beforeEach(() => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 50,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ });
+
+ it('should render scroll buttons', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-scroll-top')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-scroll-bottom')).not.toBeNull();
+ done();
+ }, 0);
+ });
- vm = mountComponentWithStore(Component, {
- props,
- store,
+ it('should render link to raw ouput', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-raw-link-controller')).not.toBeNull();
+ done();
+ }, 0);
});
- expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+ it('should render link to erase job', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull();
+ done();
+ }, 0);
+ });
});
});
});
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
index 1011512360d..413a96e502a 100644
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ b/spec/javascripts/jobs/components/job_log_spec.js
@@ -1,21 +1,32 @@
import Vue from 'vue';
import component from '~/jobs/components/job_log.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
+import createStore from '~/jobs/store';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { resetStore } from '../store/helpers';
describe('Job Log', () => {
const Component = Vue.extend(component);
+ let store;
let vm;
const trace = 'Running with gitlab-runner 11.1.0 (081978aa)<br> on docker-auto-scale-com d5ae8d25<br>Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.18-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29 ...<br>';
+ beforeEach(() => {
+ store = createStore();
+ });
+
afterEach(() => {
+ resetStore(store);
vm.$destroy();
});
it('renders provided trace', () => {
- vm = mountComponent(Component, {
- trace,
- isComplete: true,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: true,
+ },
+ store,
});
expect(vm.$el.querySelector('code').textContent).toContain('Running with gitlab-runner 11.1.0 (081978aa)');
@@ -23,9 +34,12 @@ describe('Job Log', () => {
describe('while receiving trace', () => {
it('renders animation', () => {
- vm = mountComponent(Component, {
- trace,
- isComplete: true,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: false,
+ },
+ store,
});
expect(vm.$el.querySelector('.js-log-animation')).not.toBeNull();
@@ -34,9 +48,12 @@ describe('Job Log', () => {
describe('when build trace has finishes', () => {
it('does not render animation', () => {
- vm = mountComponent(Component, {
- trace,
- isComplete: false,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: true,
+ },
+ store,
});
expect(vm.$el.querySelector('.js-log-animation')).toBeNull();
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
index ca4f62bd6ef..460a2e1b5da 100644
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -18,15 +18,6 @@ describe('Sidebar details block', () => {
vm.$destroy();
});
- describe('when it is loading', () => {
- it('should render a loading spinner', () => {
- store.dispatch('requestJob');
- vm = mountComponentWithStore(SidebarComponent, { store });
-
- expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
- });
- });
-
describe('when there is no retry path retry', () => {
it('should not render a retry button', () => {
const copy = Object.assign({}, job);
@@ -52,12 +43,12 @@ describe('Sidebar details block', () => {
describe('with terminal path', () => {
it('renders terminal link', () => {
- store.dispatch('receiveJobSuccess', job);
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, { terminal_path: 'job/43123/terminal' }),
+ );
vm = mountComponentWithStore(SidebarComponent, {
store,
- props: {
- terminalPath: 'job/43123/terminal',
- },
});
expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js
index 4269b42e8b6..ca6fbabeeb6 100644
--- a/spec/javascripts/jobs/mock_data.js
+++ b/spec/javascripts/jobs/mock_data.js
@@ -31,6 +31,7 @@ export default {
},
coverage: 20,
erased_at: threeWeeksAgo.toISOString(),
+ erased: false,
duration: 6.785563,
tags: ['tag'],
user: {
@@ -131,6 +132,7 @@ export default {
path: '/root/ci-mock/merge_requests/2',
},
raw_path: '/root/ci-mock/builds/4757/raw',
+ has_trace: true,
};
export const stages = [
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
index bc410ae614c..76af08b367d 100644
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ b/spec/javascripts/jobs/store/actions_spec.js
@@ -2,9 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import {
setJobEndpoint,
- setTraceEndpoint,
- setStagesEndpoint,
- setJobsEndpoint,
+ setTraceOptions,
clearEtagPoll,
stopPolling,
requestJob,
@@ -18,10 +16,6 @@ import {
stopPollingTrace,
receiveTraceSuccess,
receiveTraceError,
- fetchFavicon,
- requestStatusFavicon,
- receiveStatusFaviconSuccess,
- requestStatusFaviconError,
requestStages,
fetchStages,
receiveStagesSuccess,
@@ -30,6 +24,9 @@ import {
fetchJobsForStage,
receiveJobsForStageSuccess,
receiveJobsForStageError,
+ hideSidebar,
+ showSidebar,
+ toggleSidebar,
} from '~/jobs/store/actions';
import state from '~/jobs/store/state';
import * as types from '~/jobs/store/mutation_types';
@@ -56,45 +53,75 @@ describe('Job State actions', () => {
});
});
- describe('setTraceEndpoint', () => {
- it('should commit SET_TRACE_ENDPOINT mutation', done => {
+ describe('setTraceOptions', () => {
+ it('should commit SET_TRACE_OPTIONS mutation', done => {
testAction(
- setTraceEndpoint,
- 'job/872324/trace.json',
+ setTraceOptions,
+ { pagePath: 'job/872324/trace.json' },
mockedState,
- [{ type: types.SET_TRACE_ENDPOINT, payload: 'job/872324/trace.json' }],
+ [{ type: types.SET_TRACE_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }],
[],
done,
);
});
});
- describe('setStagesEndpoint', () => {
- it('should commit SET_STAGES_ENDPOINT mutation', done => {
+ describe('hideSidebar', () => {
+ it('should commit HIDE_SIDEBAR mutation', done => {
testAction(
- setStagesEndpoint,
- 'job/872324/stages.json',
+ hideSidebar,
+ null,
mockedState,
- [{ type: types.SET_STAGES_ENDPOINT, payload: 'job/872324/stages.json' }],
+ [{ type: types.HIDE_SIDEBAR }],
[],
done,
);
});
});
- describe('setJobsEndpoint', () => {
- it('should commit SET_JOBS_ENDPOINT mutation', done => {
+ describe('showSidebar', () => {
+ it('should commit HIDE_SIDEBAR mutation', done => {
testAction(
- setJobsEndpoint,
- 'job/872324/stages/build.json',
+ showSidebar,
+ null,
mockedState,
- [{ type: types.SET_JOBS_ENDPOINT, payload: 'job/872324/stages/build.json' }],
+ [{ type: types.SHOW_SIDEBAR }],
[],
done,
);
});
});
+ describe('toggleSidebar', () => {
+ describe('when isSidebarOpen is true', () => {
+ it('should dispatch hideSidebar', done => {
+ testAction(
+ toggleSidebar,
+ null,
+ mockedState,
+ [],
+ [{ type: 'hideSidebar' }],
+ done,
+ );
+ });
+ });
+
+ describe('when isSidebarOpen is false', () => {
+ it('should dispatch showSidebar', done => {
+ mockedState.isSidebarOpen = false;
+
+ testAction(
+ toggleSidebar,
+ null,
+ mockedState,
+ [],
+ [{ type: 'showSidebar' }],
+ done,
+ );
+ });
+ });
+ });
+
describe('requestJob', () => {
it('should commit REQUEST_JOB mutation', done => {
testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], [], done);
@@ -183,14 +210,14 @@ describe('Job State actions', () => {
});
describe('scrollTop', () => {
- it('should commit SCROLL_TO_TOP mutation', done => {
- testAction(scrollTop, null, mockedState, [{ type: types.SCROLL_TO_TOP }], [], done);
+ it('should dispatch toggleScrollButtons action', done => {
+ testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
describe('scrollBottom', () => {
- it('should commit SCROLL_TO_BOTTOM mutation', done => {
- testAction(scrollBottom, null, mockedState, [{ type: types.SCROLL_TO_BOTTOM }], [], done);
+ it('should dispatch toggleScrollButtons action', done => {
+ testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
@@ -215,7 +242,7 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestTrace, fetchFavicon, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
+ it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, {
html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
complete: true,
@@ -228,10 +255,8 @@ describe('Job State actions', () => {
[],
[
{
- type: 'requestTrace',
- },
- {
- type: 'fetchFavicon',
+ type: 'toggleScrollisInBottom',
+ payload: true,
},
{
payload: {
@@ -262,9 +287,6 @@ describe('Job State actions', () => {
[],
[
{
- type: 'requestTrace',
- },
- {
type: 'receiveTraceError',
},
],
@@ -313,104 +335,6 @@ describe('Job State actions', () => {
});
});
- describe('fetchFavicon', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.pagePath = `${TEST_HOST}/endpoint`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('success', () => {
- it('dispatches requestStatusFavicon and receiveStatusFaviconSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint/status.json`).replyOnce(200);
-
- testAction(
- fetchFavicon,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStatusFavicon',
- },
- {
- type: 'receiveStatusFaviconSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint/status.json`).replyOnce(500);
- });
-
- it('dispatches requestStatusFavicon and requestStatusFaviconError ', done => {
- testAction(
- fetchFavicon,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStatusFavicon',
- },
- {
- type: 'requestStatusFaviconError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('requestStatusFavicon', () => {
- it('should commit REQUEST_STATUS_FAVICON mutation ', done => {
- testAction(
- requestStatusFavicon,
- null,
- mockedState,
- [{ type: types.REQUEST_STATUS_FAVICON }],
- [],
- done,
- );
- });
- });
-
- describe('receiveStatusFaviconSuccess', () => {
- it('should commit RECEIVE_STATUS_FAVICON_SUCCESS mutation ', done => {
- testAction(
- receiveStatusFaviconSuccess,
- null,
- mockedState,
- [{ type: types.RECEIVE_STATUS_FAVICON_SUCCESS }],
- [],
- done,
- );
- });
- });
-
- describe('requestStatusFaviconError', () => {
- it('should commit RECEIVE_STATUS_FAVICON_ERROR mutation ', done => {
- testAction(
- requestStatusFaviconError,
- null,
- mockedState,
- [{ type: types.RECEIVE_STATUS_FAVICON_ERROR }],
- [],
- done,
- );
- });
- });
-
describe('requestStages', () => {
it('should commit REQUEST_STAGES mutation ', done => {
testAction(requestStages, null, mockedState, [{ type: types.REQUEST_STAGES }], [], done);
diff --git a/spec/javascripts/jobs/store/helpers.js b/spec/javascripts/jobs/store/helpers.js
new file mode 100644
index 00000000000..81a769b4a6e
--- /dev/null
+++ b/spec/javascripts/jobs/store/helpers.js
@@ -0,0 +1,6 @@
+import state from '~/jobs/store/state';
+
+// eslint-disable-next-line import/prefer-default-export
+export const resetStore = store => {
+ store.replaceState(state());
+};
diff --git a/spec/javascripts/jobs/store/mutations_spec.js b/spec/javascripts/jobs/store/mutations_spec.js
index c058a3b3d51..9bbf4ba8951 100644
--- a/spec/javascripts/jobs/store/mutations_spec.js
+++ b/spec/javascripts/jobs/store/mutations_spec.js
@@ -20,27 +20,19 @@ describe('Jobs Store Mutations', () => {
});
});
- describe('REQUEST_STATUS_FAVICON', () => {
- it('should set fetchingStatusFavicon to true', () => {
- mutations[types.REQUEST_STATUS_FAVICON](stateCopy);
+ describe('HIDE_SIDEBAR', () => {
+ it('should set isSidebarOpen to false', () => {
+ mutations[types.HIDE_SIDEBAR](stateCopy);
- expect(stateCopy.fetchingStatusFavicon).toEqual(true);
+ expect(stateCopy.isSidebarOpen).toEqual(false);
});
});
- describe('RECEIVE_STATUS_FAVICON_SUCCESS', () => {
- it('should set fetchingStatusFavicon to false', () => {
- mutations[types.RECEIVE_STATUS_FAVICON_SUCCESS](stateCopy);
+ describe('SHOW_SIDEBAR', () => {
+ it('should set isSidebarOpen to true', () => {
+ mutations[types.SHOW_SIDEBAR](stateCopy);
- expect(stateCopy.fetchingStatusFavicon).toEqual(false);
- });
- });
-
- describe('RECEIVE_STATUS_FAVICON_ERROR', () => {
- it('should set fetchingStatusFavicon to false', () => {
- mutations[types.RECEIVE_STATUS_FAVICON_ERROR](stateCopy);
-
- expect(stateCopy.fetchingStatusFavicon).toEqual(false);
+ expect(stateCopy.isSidebarOpen).toEqual(true);
});
});
@@ -101,9 +93,7 @@ describe('Jobs Store Mutations', () => {
it('resets trace state and sets error to true', () => {
mutations[types.RECEIVE_TRACE_ERROR](stateCopy);
- expect(stateCopy.isLoadingTrace).toEqual(false);
expect(stateCopy.isTraceComplete).toEqual(true);
- expect(stateCopy.hasTraceError).toEqual(true);
});
});
@@ -156,39 +146,10 @@ describe('Jobs Store Mutations', () => {
mutations[types.RECEIVE_JOB_ERROR](stateCopy);
expect(stateCopy.isLoading).toEqual(false);
- expect(stateCopy.hasError).toEqual(true);
expect(stateCopy.job).toEqual({});
});
});
- describe('SCROLL_TO_TOP', () => {
- beforeEach(() => {
- mutations[types.SCROLL_TO_TOP](stateCopy);
- });
-
- it('sets isTraceScrolledToBottom to false', () => {
- expect(stateCopy.isTraceScrolledToBottom).toEqual(false);
- });
-
- it('sets hasBeenScrolled to true', () => {
- expect(stateCopy.hasBeenScrolled).toEqual(true);
- });
- });
-
- describe('SCROLL_TO_BOTTOM', () => {
- beforeEach(() => {
- mutations[types.SCROLL_TO_BOTTOM](stateCopy);
- });
-
- it('sets isTraceScrolledToBottom to true', () => {
- expect(stateCopy.isTraceScrolledToBottom).toEqual(true);
- });
-
- it('sets hasBeenScrolled to true', () => {
- expect(stateCopy.hasBeenScrolled).toEqual(true);
- });
- });
-
describe('REQUEST_STAGES', () => {
it('sets isLoadingStages to true', () => {
mutations[types.REQUEST_STAGES](stateCopy);
diff --git a/spec/javascripts/pipelines/graph/dropdown_job_component_spec.js b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
index 2b47ca236b2..24631cc1c89 100644
--- a/spec/javascripts/pipelines/graph/dropdown_job_component_spec.js
+++ b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
@@ -1,12 +1,12 @@
import Vue from 'vue';
-import component from '~/pipelines/components/graph/dropdown_job_component.vue';
+import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-describe('dropdown job component', () => {
- const Component = Vue.extend(component);
+describe('job group dropdown component', () => {
+ const Component = Vue.extend(JobGroupDropdown);
let vm;
- const mock = {
+ const group = {
jobs: [
{
id: 4256,
@@ -71,15 +71,15 @@ describe('dropdown job component', () => {
});
beforeEach(() => {
- vm = mountComponent(Component, { job: mock });
+ vm = mountComponent(Component, { group });
});
- it('renders button with job name and size', () => {
- expect(vm.$el.querySelector('button').textContent).toContain(mock.name);
- expect(vm.$el.querySelector('button').textContent).toContain(mock.size);
+ it('renders button with group name and size', () => {
+ expect(vm.$el.querySelector('button').textContent).toContain(group.name);
+ expect(vm.$el.querySelector('button').textContent).toContain(group.size);
});
it('renders dropdown with jobs', () => {
- expect(vm.$el.querySelectorAll('.scrollable-menu>ul>li').length).toEqual(mock.jobs.length);
+ expect(vm.$el.querySelectorAll('.scrollable-menu>ul>li').length).toEqual(group.jobs.length);
});
});
diff --git a/spec/javascripts/pipelines/graph/job_component_spec.js b/spec/javascripts/pipelines/graph/job_item_spec.js
index 0ae448f2ea8..88bc4676699 100644
--- a/spec/javascripts/pipelines/graph/job_component_spec.js
+++ b/spec/javascripts/pipelines/graph/job_item_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import jobComponent from '~/pipelines/components/graph/job_component.vue';
+import JobItem from '~/pipelines/components/graph/job_item.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-describe('pipeline graph job component', () => {
- const JobComponent = Vue.extend(jobComponent);
+describe('pipeline graph job item', () => {
+ const JobComponent = Vue.extend(JobItem);
let component;
const mockJob = {
diff --git a/spec/javascripts/pipelines/graph/stage_column_component_spec.js b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
index f6e6bd3132e..d0b8f877d6f 100644
--- a/spec/javascripts/pipelines/graph/stage_column_component_spec.js
+++ b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
@@ -25,17 +25,16 @@ describe('stage column component', () => {
};
beforeEach(() => {
-
- const mockJobs = [];
+ const mockGroups = [];
for (let i = 0; i < 3; i += 1) {
const mockedJob = Object.assign({}, mockJob);
mockedJob.id += i;
- mockJobs.push(mockedJob);
+ mockGroups.push(mockedJob);
}
component = mountComponent(StageColumnComponent, {
title: 'foo',
- jobs: mockJobs,
+ groups: mockGroups,
});
});
@@ -43,14 +42,14 @@ describe('stage column component', () => {
expect(component.$el.querySelector('.stage-name').textContent.trim()).toEqual('foo');
});
- it('should render the provided jobs', () => {
+ it('should render the provided groups', () => {
expect(component.$el.querySelectorAll('.builds-container > ul > li').length).toEqual(3);
});
describe('jobId', () => {
it('escapes job name', () => {
component = mountComponent(StageColumnComponent, {
- jobs: [
+ groups: [
{
id: 4259,
name: '<img src=x onerror=alert(document.domain)>',
@@ -64,9 +63,9 @@ describe('stage column component', () => {
title: 'test',
});
- expect(
- component.$el.querySelector('.builds-container li').getAttribute('id'),
- ).toEqual('ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;');
+ expect(component.$el.querySelector('.builds-container li').getAttribute('id')).toEqual(
+ 'ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;',
+ );
});
});
});
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
index f17818c17c7..43750c74b99 100644
--- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js
+++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
@@ -94,7 +94,7 @@ describe('Header CI Component', () => {
});
it('should render sidebar toggle button', () => {
- expect(vm.$el.querySelector('.js-sidebar-build-toggle')).toBeDefined();
+ expect(vm.$el.querySelector('.js-sidebar-build-toggle')).not.toBeNull();
});
});