diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-05 18:09:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-05 18:09:06 +0000 |
commit | b042382bbf5a4977c5b5c6b0a9a33f4e8ca8d16d (patch) | |
tree | de31671ab7c6ca8c2a3721cbabd1f2a42b3d0194 /spec | |
parent | eabf8fd774fef6a54903e5141138f47bdafeb331 (diff) | |
download | gitlab-ce-b042382bbf5a4977c5b5c6b0a9a33f4e8ca8d16d.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
20 files changed, 2074 insertions, 1515 deletions
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 07b82bdff04..1c58c2b5c97 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -96,7 +96,7 @@ describe GroupsController do User.where(id: [admin, owner, maintainer, developer, guest]).update_all(can_create_group: can_create_group_status) end - [:admin, :owner].each do |member_type| + [:admin, :owner, :maintainer].each do |member_type| context "and logged in as #{member_type.capitalize}" do it_behaves_like 'member with ability to create subgroups' do let(:member) { send(member_type) } @@ -104,7 +104,7 @@ describe GroupsController do end end - [:guest, :developer, :maintainer].each do |member_type| + [:guest, :developer].each do |member_type| context "and logged in as #{member_type.capitalize}" do it_behaves_like 'member without ability to create subgroups' do let(:member) { send(member_type) } diff --git a/spec/factories/project_error_tracking_settings.rb b/spec/factories/project_error_tracking_settings.rb index 5d3fb284eef..e09d58d293f 100644 --- a/spec/factories/project_error_tracking_settings.rb +++ b/spec/factories/project_error_tracking_settings.rb @@ -8,5 +8,9 @@ FactoryBot.define do token { 'access_token_123' } project_name { 'Sentry Project' } organization_name { 'Sentry Org' } + + trait :disabled do + enabled { false } + end end end diff --git a/spec/features/admin/admin_mode/workers_spec.rb b/spec/features/admin/admin_mode/workers_spec.rb new file mode 100644 index 00000000000..8c515b8d220 --- /dev/null +++ b/spec/features/admin/admin_mode/workers_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# Test an operation that triggers background jobs requiring administrative rights +describe 'Admin mode for workers', :do_not_mock_admin_mode, :request_store, :clean_gitlab_redis_shared_state do + let(:user) { create(:user) } + let(:user_to_delete) { create(:user) } + + before do + add_sidekiq_middleware + + sign_in(user) + end + + context 'as a regular user' do + it 'cannot delete user' do + visit admin_user_path(user_to_delete) + + expect(page).to have_gitlab_http_status(:not_found) + end + end + + context 'as an admin user' do + let(:user) { create(:admin) } + + context 'when admin mode disabled' do + it 'cannot delete user', :js do + visit admin_user_path(user_to_delete) + + expect(page).to have_content('Re-authentication required') + end + end + + context 'when admin mode enabled', :delete do + before do + gitlab_enable_admin_mode_sign_in(user) + end + + it 'can delete user', :sidekiq, :js do + visit admin_user_path(user_to_delete) + click_button 'Delete user' + + page.within '.modal-dialog' do + find("input[name='username']").send_keys(user_to_delete.name) + click_button 'Delete user' + + wait_for_requests + end + + expect(page).to have_content('The user is being deleted.') + + # Perform jobs while logged out so that admin mode is only enabled in job metadata + execute_jobs_signed_out(user) + + visit admin_user_path(user_to_delete) + + expect(page).to have_title('Not Found') + end + end + end + + def add_sidekiq_middleware + Sidekiq::Testing.server_middleware do |chain| + chain.add Gitlab::SidekiqMiddleware::AdminMode::Server + end + end + + def execute_jobs_signed_out(user) + gitlab_sign_out + + Sidekiq::Worker.drain_all + + sign_in(user) + gitlab_enable_admin_mode_sign_in(user) + end +end diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index 3e8197588ed..954773e766d 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -2,46 +2,64 @@ require 'spec_helper' -describe 'Admin uses repository checks' do +describe 'Admin uses repository checks', :request_store, :clean_gitlab_redis_shared_state, :do_not_mock_admin_mode do include StubENV + let(:admin) { create(:admin) } + before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - sign_in(create(:admin)) + sign_in(admin) end - it 'to trigger a single check' do - project = create(:project) - visit_admin_project_page(project) + context 'when admin mode is disabled' do + it 'admin project page requires admin mode' do + project = create(:project) + visit_admin_project_page(project) - page.within('.repository-check') do - click_button 'Trigger repository check' + expect(page).not_to have_css('.repository-check') + expect(page).to have_content('Enter Admin Mode') end - - expect(page).to have_content('Repository check was triggered') end - it 'to see a single failed repository check', :js do - project = create(:project) - project.update_columns( - last_repository_check_failed: true, - last_repository_check_at: Time.now - ) - visit_admin_project_page(project) + context 'when admin mode is enabled' do + before do + gitlab_enable_admin_mode_sign_in(admin) + end + + it 'to trigger a single check', :js do + project = create(:project) + visit_admin_project_page(project) + + page.within('.repository-check') do + click_button 'Trigger repository check' + end - page.within('.alert') do - expect(page.text).to match(/Last repository check \(just now\) failed/) + expect(page).to have_content('Repository check was triggered') end - end - it 'to clear all repository checks', :js do - visit repository_admin_application_settings_path + it 'to see a single failed repository check', :js do + project = create(:project) + project.update_columns( + last_repository_check_failed: true, + last_repository_check_at: Time.now + ) + visit_admin_project_page(project) + + page.within('.alert') do + expect(page.text).to match(/Last repository check \(just now\) failed/) + end + end - expect(RepositoryCheck::ClearWorker).to receive(:perform_async) + it 'to clear all repository checks', :js do + visit repository_admin_application_settings_path - accept_confirm { find(:link, 'Clear all repository checks').send_keys(:return) } + expect(RepositoryCheck::ClearWorker).to receive(:perform_async) - expect(page).to have_content('Started asynchronous removal of all repository check states.') + accept_confirm { find(:link, 'Clear all repository checks').send_keys(:return) } + + expect(page).to have_content('Started asynchronous removal of all repository check states.') + end end def visit_admin_project_page(project) diff --git a/spec/frontend/helpers/dom_shims/index.js b/spec/frontend/helpers/dom_shims/index.js index 1fc5130cefc..95a28f8bfbd 100644 --- a/spec/frontend/helpers/dom_shims/index.js +++ b/spec/frontend/helpers/dom_shims/index.js @@ -1,2 +1,3 @@ import './get_client_rects'; import './inner_text'; +import './window_scroll_to'; diff --git a/spec/frontend/helpers/dom_shims/window_scroll_to.js b/spec/frontend/helpers/dom_shims/window_scroll_to.js new file mode 100644 index 00000000000..20ae1910bf3 --- /dev/null +++ b/spec/frontend/helpers/dom_shims/window_scroll_to.js @@ -0,0 +1 @@ +window.scrollTo = jest.fn(); diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js index 31b49c45908..8fa289bbe4d 100644 --- a/spec/javascripts/jobs/components/job_app_spec.js +++ b/spec/frontend/jobs/components/job_app_spec.js @@ -1,18 +1,20 @@ -import Vue from 'vue'; +import Vuex from 'vuex'; +import { mount, createLocalVue } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; -import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; -import { waitForMutation } from 'spec/helpers/vue_test_utils_helper'; +import { getJSONFixture } from 'helpers/fixtures'; import axios from '~/lib/utils/axios_utils'; -import jobApp from '~/jobs/components/job_app.vue'; +import JobApp from '~/jobs/components/job_app.vue'; import createStore from '~/jobs/store'; -import * as types from '~/jobs/store/mutation_types'; import job from '../mock_data'; -describe('Job App ', () => { +describe('Job App', () => { + const localVue = createLocalVue(); + localVue.use(Vuex); + const delayedJobFixture = getJSONFixture('jobs/delayed.json'); - const Component = Vue.extend(jobApp); + let store; - let vm; + let wrapper; let mock; const initSettings = { @@ -32,16 +34,24 @@ describe('Job App ', () => { subscriptionsMoreMinutesUrl: 'https://customers.gitlab.com/buy_pipeline_minutes', }; - const waitForJobReceived = () => waitForMutation(store, types.RECEIVE_JOB_SUCCESS); + const createComponent = () => { + wrapper = mount(JobApp, { propsData: { ...props }, store }); + }; + const setupAndMount = ({ jobData = {}, traceData = {} } = {}) => { mock.onGet(initSettings.endpoint).replyOnce(200, { ...job, ...jobData }); mock.onGet(`${initSettings.pagePath}/trace.json`).reply(200, traceData); - store.dispatch('init', initSettings); + const asyncInit = store.dispatch('init', initSettings); - vm = mountComponentWithStore(Component, { props, store }); + createComponent(); - return waitForJobReceived(); + return asyncInit + .then(() => { + jest.runOnlyPendingTimers(); + }) + .then(() => axios.waitForAll()) + .then(() => wrapper.vm.$nextTick()); }; beforeEach(() => { @@ -50,94 +60,81 @@ describe('Job App ', () => { }); afterEach(() => { - vm.$destroy(); + wrapper.destroy(); mock.restore(); }); describe('while loading', () => { beforeEach(() => { - setupAndMount(); + store.state.isLoading = true; + createComponent(); }); it('renders loading icon', () => { - 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(); + expect(wrapper.find('.js-job-loading').exists()).toBe(true); + expect(wrapper.find('.js-job-sidebar').exists()).toBe(false); + expect(wrapper.find('.js-job-content').exists()).toBe(false); }); }); describe('with successful request', () => { describe('Header section', () => { describe('job callout message', () => { - it('should not render the reason when reason is absent', done => { - setupAndMount() - .then(() => { - expect(vm.shouldRenderCalloutMessage).toBe(false); - }) - .then(done) - .catch(done.fail); - }); + it('should not render the reason when reason is absent', () => + setupAndMount().then(() => { + expect(wrapper.vm.shouldRenderCalloutMessage).toBe(false); + })); - it('should render the reason when reason is present', done => { + it('should render the reason when reason is present', () => setupAndMount({ jobData: { callout_message: 'There is an unkown failure, please try again', }, - }) - .then(() => { - expect(vm.shouldRenderCalloutMessage).toBe(true); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.vm.shouldRenderCalloutMessage).toBe(true); + })); }); describe('triggered job', () => { - beforeEach(done => { + beforeEach(() => { const aYearAgo = new Date(); aYearAgo.setFullYear(aYearAgo.getFullYear() - 1); - setupAndMount({ jobData: { started: aYearAgo.toISOString() } }) - .then(done) - .catch(done.fail); + return setupAndMount({ jobData: { started: aYearAgo.toISOString() } }); }); it('should render provided job information', () => { expect( - vm.$el - .querySelector('.header-main-content') - .textContent.replace(/\s+/g, ' ') + wrapper + .find('.header-main-content') + .text() + .replace(/\s+/g, ' ') .trim(), ).toContain('passed Job #4757 triggered 1 year ago by Root'); }); it('should render new issue link', () => { - expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual( - job.new_issue_path, - ); + expect(wrapper.find('.js-new-issue').attributes('href')).toEqual(job.new_issue_path); }); }); describe('created job', () => { - it('should render created key', done => { - setupAndMount() - .then(() => { - expect( - vm.$el - .querySelector('.header-main-content') - .textContent.replace(/\s+/g, ' ') - .trim(), - ).toContain('passed Job #4757 created 3 weeks ago by Root'); - }) - .then(done) - .catch(done.fail); - }); + it('should render created key', () => + setupAndMount().then(() => { + expect( + wrapper + .find('.header-main-content') + .text() + .replace(/\s+/g, ' ') + .trim(), + ).toContain('passed Job #4757 created 3 weeks ago by Root'); + })); }); }); describe('stuck block', () => { describe('without active runners availabl', () => { - it('renders stuck block when there are no runners', done => { + it('renders stuck block when there are no runners', () => setupAndMount({ jobData: { status: { @@ -154,20 +151,14 @@ describe('Job App ', () => { }, tags: [], }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull(); - expect( - vm.$el.querySelector('.js-job-stuck .js-stuck-no-active-runner'), - ).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-stuck').exists()).toBe(true); + expect(wrapper.find('.js-job-stuck .js-stuck-no-active-runner').exists()).toBe(true); + })); }); describe('when available runners can not run specified tag', () => { - it('renders tags in stuck block when there are no runners', done => { + it('renders tags in stuck block when there are no runners', () => setupAndMount({ jobData: { status: { @@ -183,18 +174,14 @@ describe('Job App ', () => { online: false, }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]); - expect(vm.$el.querySelector('.js-job-stuck .js-stuck-with-tags')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-stuck').text()).toContain(job.tags[0]); + expect(wrapper.find('.js-job-stuck .js-stuck-with-tags').exists()).toBe(true); + })); }); describe('when runners are offline and build has tags', () => { - it('renders message about job being stuck because of no runners with the specified tags', done => { + it('renders message about job being stuck because of no runners with the specified tags', () => setupAndMount({ jobData: { status: { @@ -210,32 +197,24 @@ describe('Job App ', () => { online: true, }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]); - expect(vm.$el.querySelector('.js-job-stuck .js-stuck-with-tags')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-stuck').text()).toContain(job.tags[0]); + expect(wrapper.find('.js-job-stuck .js-stuck-with-tags').exists()).toBe(true); + })); }); - it('does not renders stuck block when there are no runners', done => { + it('does not renders stuck block when there are no runners', () => setupAndMount({ jobData: { runners: { available: true }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-stuck')).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-stuck').exists()).toBe(false); + })); }); describe('unmet prerequisites block', () => { - it('renders unmet prerequisites block when there is an unmet prerequisites failure', done => { + it('renders unmet prerequisites block when there is an unmet prerequisites failure', () => setupAndMount({ jobData: { status: { @@ -258,17 +237,13 @@ describe('Job App ', () => { }, tags: [], }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-failed')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-failed').exists()).toBe(true); + })); }); describe('environments block', () => { - it('renders environment block when job has environment', done => { + it('renders environment block when job has environment', () => setupAndMount({ jobData: { deployment_status: { @@ -278,26 +253,18 @@ describe('Job App ', () => { }, }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-environment')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); - - it('does not render environment block when job has environment', done => { - setupAndMount() - .then(() => { - expect(vm.$el.querySelector('.js-job-environment')).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-environment').exists()).toBe(true); + })); + + it('does not render environment block when job has environment', () => + setupAndMount().then(() => { + expect(wrapper.find('.js-job-environment').exists()).toBe(false); + })); }); describe('erased block', () => { - it('renders erased block when `erased` is true', done => { + it('renders erased block when `erased` is true', () => setupAndMount({ jobData: { erased_by: { @@ -306,30 +273,22 @@ describe('Job App ', () => { }, erased_at: '2016-11-07T11:11:16.525Z', }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-erased-block')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-erased-block').exists()).toBe(true); + })); - it('does not render erased block when `erased` is false', done => { + it('does not render erased block when `erased` is false', () => setupAndMount({ jobData: { erased_at: null, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-erased-block')).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-erased-block').exists()).toBe(false); + })); }); describe('empty states block', () => { - it('renders empty state when job does not have trace and is not running', done => { + it('renders empty state when job does not have trace and is not running', () => setupAndMount({ jobData: { has_trace: false, @@ -352,15 +311,11 @@ describe('Job App ', () => { }, }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-empty-state').exists()).toBe(true); + })); - it('does not render empty state when job does not have trace but it is running', done => { + it('does not render empty state when job does not have trace but it is running', () => setupAndMount({ jobData: { has_trace: false, @@ -372,38 +327,29 @@ describe('Job App ', () => { details_path: 'path', }, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect(wrapper.find('.js-job-empty-state').exists()).toBe(false); + })); - it('does not render empty state when job has trace but it is not running', done => { - setupAndMount({ jobData: { has_trace: true } }) - .then(() => { - expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull(); - }) - .then(done) - .catch(done.fail); - }); + it('does not render empty state when job has trace but it is not running', () => + setupAndMount({ jobData: { has_trace: true } }).then(() => { + expect(wrapper.find('.js-job-empty-state').exists()).toBe(false); + })); - it('displays remaining time for a delayed job', done => { + it('displays remaining time for a delayed job', () => { const oneHourInMilliseconds = 3600000; - spyOn(Date, 'now').and.callFake( - () => new Date(delayedJobFixture.scheduled_at).getTime() - oneHourInMilliseconds, - ); - setupAndMount({ jobData: delayedJobFixture }) - .then(() => { - expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull(); + jest + .spyOn(Date, 'now') + .mockImplementation( + () => new Date(delayedJobFixture.scheduled_at).getTime() - oneHourInMilliseconds, + ); + return setupAndMount({ jobData: delayedJobFixture }).then(() => { + expect(wrapper.find('.js-job-empty-state').exists()).toBe(true); - const title = vm.$el.querySelector('.js-job-empty-state-title'); + const title = wrapper.find('.js-job-empty-state-title').text(); - expect(title).toContainText('01:00:00'); - }) - .then(done) - .catch(done.fail); + expect(title).toEqual('This is a delayed job to run in 01:00:00'); + }); }); }); @@ -422,8 +368,11 @@ describe('Job App ', () => { }, }) .then(() => { - vm.$el.querySelectorAll('.blocks-container > *').forEach(block => { - expect(block.textContent.trim()).not.toBe(''); + const blocks = wrapper.findAll('.blocks-container > *').wrappers; + expect(blocks.length).toBeGreaterThan(0); + + blocks.forEach(block => { + expect(block.text().trim()).not.toBe(''); }); }) .then(done) @@ -433,32 +382,24 @@ describe('Job App ', () => { }); describe('archived job', () => { - beforeEach(done => { - setupAndMount({ jobData: { archived: true } }) - .then(done) - .catch(done.fail); - }); + beforeEach(() => setupAndMount({ jobData: { archived: true } })); it('renders warning about job being archived', () => { - expect(vm.$el.querySelector('.js-archived-job ')).not.toBeNull(); + expect(wrapper.find('.js-archived-job ').exists()).toBe(true); }); }); describe('non-archived job', () => { - beforeEach(done => { - setupAndMount() - .then(done) - .catch(done.fail); - }); + beforeEach(() => setupAndMount()); it('does not warning about job being archived', () => { - expect(vm.$el.querySelector('.js-archived-job ')).toBeNull(); + expect(wrapper.find('.js-archived-job ').exists()).toBe(false); }); }); describe('trace output', () => { describe('with append flag', () => { - it('appends the log content to the existing one', done => { + it('appends the log content to the existing one', () => setupAndMount({ traceData: { html: '<span>More<span>', @@ -469,20 +410,22 @@ describe('Job App ', () => { }, }) .then(() => { - vm.$store.state.trace = 'Update'; + store.state.trace = 'Update'; - return vm.$nextTick(); + return wrapper.vm.$nextTick(); }) .then(() => { - expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain('Update'); - }) - .then(done) - .catch(done.fail); - }); + expect( + wrapper + .find('.js-build-trace') + .text() + .trim(), + ).toEqual('Update'); + })); }); describe('without append flag', () => { - it('replaces the trace', done => { + it('replaces the trace', () => setupAndMount({ traceData: { html: '<span>Different<span>', @@ -490,24 +433,19 @@ describe('Job App ', () => { append: false, complete: true, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).not.toContain( - 'Update', - ); - - expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain( - 'Different', - ); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect( + wrapper + .find('.js-build-trace') + .text() + .trim(), + ).toEqual('Different'); + })); }); describe('truncated information', () => { describe('when size is less than total', () => { - it('shows information about truncated log', done => { + it('shows information about truncated log', () => { mock.onGet(`${props.pagePath}/trace.json`).reply(200, { html: '<span>Update</span>', status: 'success', @@ -517,7 +455,7 @@ describe('Job App ', () => { complete: true, }); - setupAndMount({ + return setupAndMount({ traceData: { html: '<span>Update</span>', status: 'success', @@ -526,19 +464,19 @@ describe('Job App ', () => { total: 100, complete: true, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).toContain( - '50 bytes', - ); - }) - .then(done) - .catch(done.fail); + }).then(() => { + expect( + wrapper + .find('.js-truncated-info') + .text() + .trim(), + ).toContain('Showing last 50 bytes'); + }); }); }); describe('when size is equal than total', () => { - it('does not show the truncated information', done => { + it('does not show the truncated information', () => setupAndMount({ traceData: { html: '<span>Update</span>', @@ -548,20 +486,19 @@ describe('Job App ', () => { total: 100, complete: true, }, - }) - .then(() => { - expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).not.toContain( - '50 bytes', - ); - }) - .then(done) - .catch(done.fail); - }); + }).then(() => { + expect( + wrapper + .find('.js-truncated-info') + .text() + .trim(), + ).toEqual(''); + })); }); }); describe('trace controls', () => { - beforeEach(done => { + beforeEach(() => setupAndMount({ traceData: { html: '<span>Update</span>', @@ -571,22 +508,20 @@ describe('Job App ', () => { total: 100, complete: true, }, - }) - .then(done) - .catch(done.fail); - }); + }), + ); it('should render scroll buttons', () => { - expect(vm.$el.querySelector('.js-scroll-top')).not.toBeNull(); - expect(vm.$el.querySelector('.js-scroll-bottom')).not.toBeNull(); + expect(wrapper.find('.js-scroll-top').exists()).toBe(true); + expect(wrapper.find('.js-scroll-bottom').exists()).toBe(true); }); it('should render link to raw ouput', () => { - expect(vm.$el.querySelector('.js-raw-link-controller')).not.toBeNull(); + expect(wrapper.find('.js-raw-link-controller').exists()).toBe(true); }); it('should render link to erase job', () => { - expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull(); + expect(wrapper.find('.js-erase-link').exists()).toBe(true); }); }); }); diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js new file mode 100644 index 00000000000..3d40e94d219 --- /dev/null +++ b/spec/frontend/jobs/mock_data.js @@ -0,0 +1,1191 @@ +import { TEST_HOST } from 'spec/test_constants'; + +const threeWeeksAgo = new Date(); +threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21); + +export const stages = [ + { + name: 'build', + title: 'build: running', + groups: [ + { + name: 'build:linux', + size: 1, + status: { + icon: 'status_pending', + text: 'pending', + label: 'pending', + group: 'pending', + tooltip: 'pending', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', + illustration: { + image: 'illustrations/pending_job_empty.svg', + size: 'svg-430', + title: 'This job has not started yet', + content: 'This job is in pending state and is waiting to be picked by a runner', + }, + favicon: + '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', + method: 'post', + }, + }, + jobs: [ + { + id: 1180, + name: 'build:linux', + started: false, + build_path: '/gitlab-org/gitlab-shell/-/jobs/1180', + cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', + playable: false, + created_at: '2018-09-28T11:09:57.229Z', + updated_at: '2018-09-28T11:09:57.503Z', + status: { + icon: 'status_pending', + text: 'pending', + label: 'pending', + group: 'pending', + tooltip: 'pending', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', + illustration: { + image: 'illustrations/pending_job_empty.svg', + size: 'svg-430', + title: 'This job has not started yet', + content: 'This job is in pending state and is waiting to be picked by a runner', + }, + favicon: + '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'build:osx', + size: 1, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/444', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', + method: 'post', + }, + }, + jobs: [ + { + id: 444, + name: 'build:osx', + started: '2018-05-18T05:32:20.655Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/444', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', + playable: false, + created_at: '2018-05-18T15:32:54.364Z', + updated_at: '2018-05-18T15:32:54.364Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/444', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', + method: 'post', + }, + }, + }, + ], + }, + ], + status: { + icon: 'status_running', + text: 'running', + label: 'running', + group: 'running', + tooltip: 'running', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/pipelines/27#build', + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', + }, + path: '/gitlab-org/gitlab-shell/pipelines/27#build', + dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build', + }, + { + name: 'test', + title: 'test: passed with warnings', + groups: [ + { + name: 'jenkins', + size: 1, + status: { + icon: 'status_success', + text: 'passed', + label: null, + group: 'success', + tooltip: null, + has_details: false, + details_path: null, + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + }, + jobs: [ + { + id: 459, + name: 'jenkins', + started: '2018-05-18T09:32:20.658Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/459', + playable: false, + created_at: '2018-05-18T15:32:55.330Z', + updated_at: '2018-05-18T15:32:55.330Z', + status: { + icon: 'status_success', + text: 'passed', + label: null, + group: 'success', + tooltip: null, + has_details: false, + details_path: null, + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + }, + }, + ], + }, + { + name: 'rspec:linux', + size: 3, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: false, + details_path: null, + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + }, + jobs: [ + { + id: 445, + name: 'rspec:linux 0 3', + started: '2018-05-18T07:32:20.655Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/445', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/445/retry', + playable: false, + created_at: '2018-05-18T15:32:54.425Z', + updated_at: '2018-05-18T15:32:54.425Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/445', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/445/retry', + method: 'post', + }, + }, + }, + { + id: 446, + name: 'rspec:linux 1 3', + started: '2018-05-18T07:32:20.655Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/446', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/446/retry', + playable: false, + created_at: '2018-05-18T15:32:54.506Z', + updated_at: '2018-05-18T15:32:54.506Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/446', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/446/retry', + method: 'post', + }, + }, + }, + { + id: 447, + name: 'rspec:linux 2 3', + started: '2018-05-18T07:32:20.656Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/447', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/447/retry', + playable: false, + created_at: '2018-05-18T15:32:54.572Z', + updated_at: '2018-05-18T15:32:54.572Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/447', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/447/retry', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'rspec:osx', + size: 1, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/452', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', + method: 'post', + }, + }, + jobs: [ + { + id: 452, + name: 'rspec:osx', + started: '2018-05-18T07:32:20.657Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/452', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', + playable: false, + created_at: '2018-05-18T15:32:54.920Z', + updated_at: '2018-05-18T15:32:54.920Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/452', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'rspec:windows', + size: 3, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: false, + details_path: null, + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + }, + jobs: [ + { + id: 448, + name: 'rspec:windows 0 3', + started: '2018-05-18T07:32:20.656Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/448', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/448/retry', + playable: false, + created_at: '2018-05-18T15:32:54.639Z', + updated_at: '2018-05-18T15:32:54.639Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/448', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/448/retry', + method: 'post', + }, + }, + }, + { + id: 449, + name: 'rspec:windows 1 3', + started: '2018-05-18T07:32:20.656Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/449', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/449/retry', + playable: false, + created_at: '2018-05-18T15:32:54.703Z', + updated_at: '2018-05-18T15:32:54.703Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/449', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/449/retry', + method: 'post', + }, + }, + }, + { + id: 451, + name: 'rspec:windows 2 3', + started: '2018-05-18T07:32:20.657Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/451', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/451/retry', + playable: false, + created_at: '2018-05-18T15:32:54.853Z', + updated_at: '2018-05-18T15:32:54.853Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/451', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/451/retry', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'spinach:linux', + size: 1, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/453', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', + method: 'post', + }, + }, + jobs: [ + { + id: 453, + name: 'spinach:linux', + started: '2018-05-18T07:32:20.657Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/453', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', + playable: false, + created_at: '2018-05-18T15:32:54.993Z', + updated_at: '2018-05-18T15:32:54.993Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/453', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'spinach:osx', + size: 1, + status: { + icon: 'status_warning', + text: 'failed', + label: 'failed (allowed to fail)', + group: 'failed-with-warnings', + tooltip: 'failed - (unknown failure) (allowed to fail)', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/454', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', + method: 'post', + }, + }, + jobs: [ + { + id: 454, + name: 'spinach:osx', + started: '2018-05-18T07:32:20.657Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/454', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', + playable: false, + created_at: '2018-05-18T15:32:55.053Z', + updated_at: '2018-05-18T15:32:55.053Z', + status: { + icon: 'status_warning', + text: 'failed', + label: 'failed (allowed to fail)', + group: 'failed-with-warnings', + tooltip: 'failed - (unknown failure) (allowed to fail)', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/454', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', + method: 'post', + }, + }, + callout_message: 'There is an unknown failure, please try again', + recoverable: true, + }, + ], + }, + ], + status: { + icon: 'status_warning', + text: 'passed', + label: 'passed with warnings', + group: 'success-with-warnings', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/pipelines/27#test', + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + }, + path: '/gitlab-org/gitlab-shell/pipelines/27#test', + dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=test', + }, + { + name: 'deploy', + title: 'deploy: running', + groups: [ + { + name: 'production', + size: 1, + status: { + icon: 'status_created', + text: 'created', + label: 'created', + group: 'created', + tooltip: 'created', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/457', + illustration: { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: 'This job has not been triggered yet', + content: + 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', + }, + favicon: + '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', + method: 'post', + }, + }, + jobs: [ + { + id: 457, + name: 'production', + started: false, + build_path: '/gitlab-org/gitlab-shell/-/jobs/457', + cancel_path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', + playable: false, + created_at: '2018-05-18T15:32:55.259Z', + updated_at: '2018-09-28T11:09:57.454Z', + status: { + icon: 'status_created', + text: 'created', + label: 'created', + group: 'created', + tooltip: 'created', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/457', + illustration: { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: 'This job has not been triggered yet', + content: + 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', + }, + favicon: + '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'staging', + size: 1, + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/455', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', + method: 'post', + }, + }, + jobs: [ + { + id: 455, + name: 'staging', + started: '2018-05-18T09:32:20.658Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/455', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', + playable: false, + created_at: '2018-05-18T15:32:55.119Z', + updated_at: '2018-05-18T15:32:55.119Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/455', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', + method: 'post', + }, + }, + }, + ], + }, + { + name: 'stop staging', + size: 1, + status: { + icon: 'status_created', + text: 'created', + label: 'created', + group: 'created', + tooltip: 'created', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/456', + illustration: { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: 'This job has not been triggered yet', + content: + 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', + }, + favicon: + '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', + method: 'post', + }, + }, + jobs: [ + { + id: 456, + name: 'stop staging', + started: false, + build_path: '/gitlab-org/gitlab-shell/-/jobs/456', + cancel_path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', + playable: false, + created_at: '2018-05-18T15:32:55.205Z', + updated_at: '2018-09-28T11:09:57.396Z', + status: { + icon: 'status_created', + text: 'created', + label: 'created', + group: 'created', + tooltip: 'created', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/456', + illustration: { + image: 'illustrations/job_not_triggered.svg', + size: 'svg-306', + title: 'This job has not been triggered yet', + content: + 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', + }, + favicon: + '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', + method: 'post', + }, + }, + }, + ], + }, + ], + status: { + icon: 'status_running', + text: 'running', + label: 'running', + group: 'running', + tooltip: 'running', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/pipelines/27#deploy', + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', + }, + path: '/gitlab-org/gitlab-shell/pipelines/27#deploy', + dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=deploy', + }, + { + name: 'notify', + title: 'notify: manual action', + groups: [ + { + name: 'slack', + size: 1, + status: { + icon: 'status_manual', + text: 'manual', + label: 'manual play action', + group: 'manual', + tooltip: 'manual action', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/458', + illustration: { + image: 'illustrations/manual_action.svg', + size: 'svg-394', + title: 'This job requires a manual action', + content: + 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments', + }, + favicon: + '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', + action: { + icon: 'play', + title: 'Play', + path: '/gitlab-org/gitlab-shell/-/jobs/458/play', + method: 'post', + }, + }, + jobs: [ + { + id: 458, + name: 'slack', + started: null, + build_path: '/gitlab-org/gitlab-shell/-/jobs/458', + play_path: '/gitlab-org/gitlab-shell/-/jobs/458/play', + playable: true, + created_at: '2018-05-18T15:32:55.303Z', + updated_at: '2018-05-18T15:34:08.535Z', + status: { + icon: 'status_manual', + text: 'manual', + label: 'manual play action', + group: 'manual', + tooltip: 'manual action', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/458', + illustration: { + image: 'illustrations/manual_action.svg', + size: 'svg-394', + title: 'This job requires a manual action', + content: + 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments', + }, + favicon: + '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', + action: { + icon: 'play', + title: 'Play', + path: '/gitlab-org/gitlab-shell/-/jobs/458/play', + method: 'post', + }, + }, + }, + ], + }, + ], + status: { + icon: 'status_manual', + text: 'manual', + label: 'manual action', + group: 'manual', + tooltip: 'manual action', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/pipelines/27#notify', + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', + }, + path: '/gitlab-org/gitlab-shell/pipelines/27#notify', + dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=notify', + }, +]; + +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: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + has_details: true, + details_path: `${TEST_HOST}/root/ci-mock/-/jobs/4757`, + favicon: + '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/root/ci-mock/-/jobs/4757/retry', + method: 'post', + }, + }, + coverage: 20, + erased_at: threeWeeksAgo.toISOString(), + erased: false, + duration: 6.785563, + tags: ['tag'], + user: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: + 'https://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: + 'https://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: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + has_details: true, + details_path: '/root/ci-mock/pipelines/140', + favicon: + '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', + }, + duration: 6, + finished_at: '2017-06-01T17:32:00.042Z', + stages: [ + { + dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=build', + name: 'build', + path: '/jashkenas/underscore/pipelines/16#build', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + }, + title: 'build: passed', + }, + { + dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=test', + name: 'test', + path: '/jashkenas/underscore/pipelines/16#test', + status: { + icon: 'status_warning', + text: 'passed', + label: 'passed with warnings', + group: 'success-with-warnings', + }, + title: 'test: passed with warnings', + }, + ], + }, + 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: + 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + author_gravatar_url: + 'https://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', + }, + }, + metadata: { + timeout_human_readable: '1m 40s', + timeout_source: 'runner', + }, + merge_request: { + iid: 2, + path: '/root/ci-mock/merge_requests/2', + }, + raw_path: '/root/ci-mock/builds/4757/raw', + has_trace: true, +}; + +export const jobsInStage = { + name: 'build', + title: 'build: running', + latest_statuses: [ + { + id: 1180, + name: 'build:linux', + started: false, + build_path: '/gitlab-org/gitlab-shell/-/jobs/1180', + cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', + playable: false, + created_at: '2018-09-28T11:09:57.229Z', + updated_at: '2018-09-28T11:09:57.503Z', + status: { + icon: 'status_pending', + text: 'pending', + label: 'pending', + group: 'pending', + tooltip: 'pending', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', + illustration: { + image: 'illustrations/pending_job_empty.svg', + size: 'svg-430', + title: 'This job has not started yet', + content: 'This job is in pending state and is waiting to be picked by a runner', + }, + favicon: + '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', + action: { + icon: 'cancel', + title: 'Cancel', + path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', + method: 'post', + }, + }, + }, + { + id: 444, + name: 'build:osx', + started: '2018-05-18T05:32:20.655Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/444', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', + playable: false, + created_at: '2018-05-18T15:32:54.364Z', + updated_at: '2018-05-18T15:32:54.364Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/444', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', + method: 'post', + }, + }, + }, + ], + retried: [ + { + id: 443, + name: 'build:linux', + started: '2018-05-18T06:32:20.655Z', + build_path: '/gitlab-org/gitlab-shell/-/jobs/443', + retry_path: '/gitlab-org/gitlab-shell/-/jobs/443/retry', + playable: false, + created_at: '2018-05-18T15:32:54.296Z', + updated_at: '2018-05-18T15:32:54.296Z', + status: { + icon: 'status_success', + text: 'passed', + label: 'passed', + group: 'success', + tooltip: 'passed (retried)', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/-/jobs/443', + illustration: { + image: 'illustrations/skipped-job_empty.svg', + size: 'svg-430', + title: 'This job does not have a trace.', + }, + favicon: + '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', + action: { + icon: 'retry', + title: 'Retry', + path: '/gitlab-org/gitlab-shell/-/jobs/443/retry', + method: 'post', + }, + }, + }, + ], + status: { + icon: 'status_running', + text: 'running', + label: 'running', + group: 'running', + tooltip: 'running', + has_details: true, + details_path: '/gitlab-org/gitlab-shell/pipelines/27#build', + illustration: null, + favicon: + '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', + }, + path: '/gitlab-org/gitlab-shell/pipelines/27#build', + dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build', +}; diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js index 3d40e94d219..f0ba46c058a 100644 --- a/spec/javascripts/jobs/mock_data.js +++ b/spec/javascripts/jobs/mock_data.js @@ -1,1191 +1,2 @@ -import { TEST_HOST } from 'spec/test_constants'; - -const threeWeeksAgo = new Date(); -threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21); - -export const stages = [ - { - name: 'build', - title: 'build: running', - groups: [ - { - name: 'build:linux', - size: 1, - status: { - icon: 'status_pending', - text: 'pending', - label: 'pending', - group: 'pending', - tooltip: 'pending', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', - illustration: { - image: 'illustrations/pending_job_empty.svg', - size: 'svg-430', - title: 'This job has not started yet', - content: 'This job is in pending state and is waiting to be picked by a runner', - }, - favicon: - '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', - method: 'post', - }, - }, - jobs: [ - { - id: 1180, - name: 'build:linux', - started: false, - build_path: '/gitlab-org/gitlab-shell/-/jobs/1180', - cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', - playable: false, - created_at: '2018-09-28T11:09:57.229Z', - updated_at: '2018-09-28T11:09:57.503Z', - status: { - icon: 'status_pending', - text: 'pending', - label: 'pending', - group: 'pending', - tooltip: 'pending', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', - illustration: { - image: 'illustrations/pending_job_empty.svg', - size: 'svg-430', - title: 'This job has not started yet', - content: 'This job is in pending state and is waiting to be picked by a runner', - }, - favicon: - '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'build:osx', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/444', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 444, - name: 'build:osx', - started: '2018-05-18T05:32:20.655Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/444', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', - playable: false, - created_at: '2018-05-18T15:32:54.364Z', - updated_at: '2018-05-18T15:32:54.364Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/444', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', - method: 'post', - }, - }, - }, - ], - }, - ], - status: { - icon: 'status_running', - text: 'running', - label: 'running', - group: 'running', - tooltip: 'running', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/pipelines/27#build', - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', - }, - path: '/gitlab-org/gitlab-shell/pipelines/27#build', - dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build', - }, - { - name: 'test', - title: 'test: passed with warnings', - groups: [ - { - name: 'jenkins', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: null, - group: 'success', - tooltip: null, - has_details: false, - details_path: null, - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - }, - jobs: [ - { - id: 459, - name: 'jenkins', - started: '2018-05-18T09:32:20.658Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/459', - playable: false, - created_at: '2018-05-18T15:32:55.330Z', - updated_at: '2018-05-18T15:32:55.330Z', - status: { - icon: 'status_success', - text: 'passed', - label: null, - group: 'success', - tooltip: null, - has_details: false, - details_path: null, - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - }, - }, - ], - }, - { - name: 'rspec:linux', - size: 3, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: false, - details_path: null, - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - }, - jobs: [ - { - id: 445, - name: 'rspec:linux 0 3', - started: '2018-05-18T07:32:20.655Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/445', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/445/retry', - playable: false, - created_at: '2018-05-18T15:32:54.425Z', - updated_at: '2018-05-18T15:32:54.425Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/445', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/445/retry', - method: 'post', - }, - }, - }, - { - id: 446, - name: 'rspec:linux 1 3', - started: '2018-05-18T07:32:20.655Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/446', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/446/retry', - playable: false, - created_at: '2018-05-18T15:32:54.506Z', - updated_at: '2018-05-18T15:32:54.506Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/446', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/446/retry', - method: 'post', - }, - }, - }, - { - id: 447, - name: 'rspec:linux 2 3', - started: '2018-05-18T07:32:20.656Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/447', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/447/retry', - playable: false, - created_at: '2018-05-18T15:32:54.572Z', - updated_at: '2018-05-18T15:32:54.572Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/447', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/447/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'rspec:osx', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/452', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 452, - name: 'rspec:osx', - started: '2018-05-18T07:32:20.657Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/452', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', - playable: false, - created_at: '2018-05-18T15:32:54.920Z', - updated_at: '2018-05-18T15:32:54.920Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/452', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/452/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'rspec:windows', - size: 3, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: false, - details_path: null, - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - }, - jobs: [ - { - id: 448, - name: 'rspec:windows 0 3', - started: '2018-05-18T07:32:20.656Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/448', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/448/retry', - playable: false, - created_at: '2018-05-18T15:32:54.639Z', - updated_at: '2018-05-18T15:32:54.639Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/448', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/448/retry', - method: 'post', - }, - }, - }, - { - id: 449, - name: 'rspec:windows 1 3', - started: '2018-05-18T07:32:20.656Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/449', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/449/retry', - playable: false, - created_at: '2018-05-18T15:32:54.703Z', - updated_at: '2018-05-18T15:32:54.703Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/449', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/449/retry', - method: 'post', - }, - }, - }, - { - id: 451, - name: 'rspec:windows 2 3', - started: '2018-05-18T07:32:20.657Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/451', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/451/retry', - playable: false, - created_at: '2018-05-18T15:32:54.853Z', - updated_at: '2018-05-18T15:32:54.853Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/451', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/451/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'spinach:linux', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/453', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 453, - name: 'spinach:linux', - started: '2018-05-18T07:32:20.657Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/453', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', - playable: false, - created_at: '2018-05-18T15:32:54.993Z', - updated_at: '2018-05-18T15:32:54.993Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/453', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/453/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'spinach:osx', - size: 1, - status: { - icon: 'status_warning', - text: 'failed', - label: 'failed (allowed to fail)', - group: 'failed-with-warnings', - tooltip: 'failed - (unknown failure) (allowed to fail)', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/454', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 454, - name: 'spinach:osx', - started: '2018-05-18T07:32:20.657Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/454', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', - playable: false, - created_at: '2018-05-18T15:32:55.053Z', - updated_at: '2018-05-18T15:32:55.053Z', - status: { - icon: 'status_warning', - text: 'failed', - label: 'failed (allowed to fail)', - group: 'failed-with-warnings', - tooltip: 'failed - (unknown failure) (allowed to fail)', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/454', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/454/retry', - method: 'post', - }, - }, - callout_message: 'There is an unknown failure, please try again', - recoverable: true, - }, - ], - }, - ], - status: { - icon: 'status_warning', - text: 'passed', - label: 'passed with warnings', - group: 'success-with-warnings', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/pipelines/27#test', - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - }, - path: '/gitlab-org/gitlab-shell/pipelines/27#test', - dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=test', - }, - { - name: 'deploy', - title: 'deploy: running', - groups: [ - { - name: 'production', - size: 1, - status: { - icon: 'status_created', - text: 'created', - label: 'created', - group: 'created', - tooltip: 'created', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/457', - illustration: { - image: 'illustrations/job_not_triggered.svg', - size: 'svg-306', - title: 'This job has not been triggered yet', - content: - 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', - }, - favicon: - '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', - method: 'post', - }, - }, - jobs: [ - { - id: 457, - name: 'production', - started: false, - build_path: '/gitlab-org/gitlab-shell/-/jobs/457', - cancel_path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', - playable: false, - created_at: '2018-05-18T15:32:55.259Z', - updated_at: '2018-09-28T11:09:57.454Z', - status: { - icon: 'status_created', - text: 'created', - label: 'created', - group: 'created', - tooltip: 'created', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/457', - illustration: { - image: 'illustrations/job_not_triggered.svg', - size: 'svg-306', - title: 'This job has not been triggered yet', - content: - 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', - }, - favicon: - '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'staging', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/455', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 455, - name: 'staging', - started: '2018-05-18T09:32:20.658Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/455', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', - playable: false, - created_at: '2018-05-18T15:32:55.119Z', - updated_at: '2018-05-18T15:32:55.119Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/455', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/455/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'stop staging', - size: 1, - status: { - icon: 'status_created', - text: 'created', - label: 'created', - group: 'created', - tooltip: 'created', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/456', - illustration: { - image: 'illustrations/job_not_triggered.svg', - size: 'svg-306', - title: 'This job has not been triggered yet', - content: - 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', - }, - favicon: - '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', - method: 'post', - }, - }, - jobs: [ - { - id: 456, - name: 'stop staging', - started: false, - build_path: '/gitlab-org/gitlab-shell/-/jobs/456', - cancel_path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', - playable: false, - created_at: '2018-05-18T15:32:55.205Z', - updated_at: '2018-09-28T11:09:57.396Z', - status: { - icon: 'status_created', - text: 'created', - label: 'created', - group: 'created', - tooltip: 'created', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/456', - illustration: { - image: 'illustrations/job_not_triggered.svg', - size: 'svg-306', - title: 'This job has not been triggered yet', - content: - 'This job depends on upstream jobs that need to succeed in order for this job to be triggered', - }, - favicon: - '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel', - method: 'post', - }, - }, - }, - ], - }, - ], - status: { - icon: 'status_running', - text: 'running', - label: 'running', - group: 'running', - tooltip: 'running', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/pipelines/27#deploy', - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', - }, - path: '/gitlab-org/gitlab-shell/pipelines/27#deploy', - dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=deploy', - }, - { - name: 'notify', - title: 'notify: manual action', - groups: [ - { - name: 'slack', - size: 1, - status: { - icon: 'status_manual', - text: 'manual', - label: 'manual play action', - group: 'manual', - tooltip: 'manual action', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/458', - illustration: { - image: 'illustrations/manual_action.svg', - size: 'svg-394', - title: 'This job requires a manual action', - content: - 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments', - }, - favicon: - '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', - action: { - icon: 'play', - title: 'Play', - path: '/gitlab-org/gitlab-shell/-/jobs/458/play', - method: 'post', - }, - }, - jobs: [ - { - id: 458, - name: 'slack', - started: null, - build_path: '/gitlab-org/gitlab-shell/-/jobs/458', - play_path: '/gitlab-org/gitlab-shell/-/jobs/458/play', - playable: true, - created_at: '2018-05-18T15:32:55.303Z', - updated_at: '2018-05-18T15:34:08.535Z', - status: { - icon: 'status_manual', - text: 'manual', - label: 'manual play action', - group: 'manual', - tooltip: 'manual action', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/458', - illustration: { - image: 'illustrations/manual_action.svg', - size: 'svg-394', - title: 'This job requires a manual action', - content: - 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments', - }, - favicon: - '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', - action: { - icon: 'play', - title: 'Play', - path: '/gitlab-org/gitlab-shell/-/jobs/458/play', - method: 'post', - }, - }, - }, - ], - }, - ], - status: { - icon: 'status_manual', - text: 'manual', - label: 'manual action', - group: 'manual', - tooltip: 'manual action', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/pipelines/27#notify', - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png', - }, - path: '/gitlab-org/gitlab-shell/pipelines/27#notify', - dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=notify', - }, -]; - -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: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: `${TEST_HOST}/root/ci-mock/-/jobs/4757`, - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/-/jobs/4757/retry', - method: 'post', - }, - }, - coverage: 20, - erased_at: threeWeeksAgo.toISOString(), - erased: false, - duration: 6.785563, - tags: ['tag'], - user: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: - 'https://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: - 'https://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: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/pipelines/140', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - }, - duration: 6, - finished_at: '2017-06-01T17:32:00.042Z', - stages: [ - { - dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=build', - name: 'build', - path: '/jashkenas/underscore/pipelines/16#build', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - }, - title: 'build: passed', - }, - { - dropdown_path: '/jashkenas/underscore/pipelines/16/stage.json?stage=test', - name: 'test', - path: '/jashkenas/underscore/pipelines/16#test', - status: { - icon: 'status_warning', - text: 'passed', - label: 'passed with warnings', - group: 'success-with-warnings', - }, - title: 'test: passed with warnings', - }, - ], - }, - 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: - 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - web_url: 'http://localhost:3000/root', - }, - author_gravatar_url: - 'https://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', - }, - }, - metadata: { - timeout_human_readable: '1m 40s', - timeout_source: 'runner', - }, - merge_request: { - iid: 2, - path: '/root/ci-mock/merge_requests/2', - }, - raw_path: '/root/ci-mock/builds/4757/raw', - has_trace: true, -}; - -export const jobsInStage = { - name: 'build', - title: 'build: running', - latest_statuses: [ - { - id: 1180, - name: 'build:linux', - started: false, - build_path: '/gitlab-org/gitlab-shell/-/jobs/1180', - cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', - playable: false, - created_at: '2018-09-28T11:09:57.229Z', - updated_at: '2018-09-28T11:09:57.503Z', - status: { - icon: 'status_pending', - text: 'pending', - label: 'pending', - group: 'pending', - tooltip: 'pending', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/1180', - illustration: { - image: 'illustrations/pending_job_empty.svg', - size: 'svg-430', - title: 'This job has not started yet', - content: 'This job is in pending state and is waiting to be picked by a runner', - }, - favicon: - '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png', - action: { - icon: 'cancel', - title: 'Cancel', - path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel', - method: 'post', - }, - }, - }, - { - id: 444, - name: 'build:osx', - started: '2018-05-18T05:32:20.655Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/444', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', - playable: false, - created_at: '2018-05-18T15:32:54.364Z', - updated_at: '2018-05-18T15:32:54.364Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/444', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/444/retry', - method: 'post', - }, - }, - }, - ], - retried: [ - { - id: 443, - name: 'build:linux', - started: '2018-05-18T06:32:20.655Z', - build_path: '/gitlab-org/gitlab-shell/-/jobs/443', - retry_path: '/gitlab-org/gitlab-shell/-/jobs/443/retry', - playable: false, - created_at: '2018-05-18T15:32:54.296Z', - updated_at: '2018-05-18T15:32:54.296Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - tooltip: 'passed (retried)', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/-/jobs/443', - illustration: { - image: 'illustrations/skipped-job_empty.svg', - size: 'svg-430', - title: 'This job does not have a trace.', - }, - favicon: - '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/gitlab-org/gitlab-shell/-/jobs/443/retry', - method: 'post', - }, - }, - }, - ], - status: { - icon: 'status_running', - text: 'running', - label: 'running', - group: 'running', - tooltip: 'running', - has_details: true, - details_path: '/gitlab-org/gitlab-shell/pipelines/27#build', - illustration: null, - favicon: - '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png', - }, - path: '/gitlab-org/gitlab-shell/pipelines/27#build', - dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build', -}; +export { default } from '../../frontend/jobs/mock_data'; +export * from '../../frontend/jobs/mock_data'; diff --git a/spec/lib/gitlab/auth/current_user_mode_spec.rb b/spec/lib/gitlab/auth/current_user_mode_spec.rb index 3b3db0f7315..7c2fdac6c25 100644 --- a/spec/lib/gitlab/auth/current_user_mode_spec.rb +++ b/spec/lib/gitlab/auth/current_user_mode_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do +describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode, :request_store do include_context 'custom session' - let(:user) { build(:user) } + let(:user) { build_stubbed(:user) } subject { described_class.new(user) } @@ -13,54 +13,66 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do allow(ActiveSession).to receive(:list_sessions).with(user).and_return([session]) end - describe '#admin_mode?', :request_store do - context 'when the user is a regular user' do - it 'is false by default' do - expect(subject.admin_mode?).to be(false) - end + shared_examples 'admin mode cannot be enabled' do + it 'is false by default' do + expect(subject.admin_mode?).to be(false) + end - it 'cannot be enabled with a valid password' do - subject.enable_admin_mode!(password: user.password) + it 'cannot be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password) - expect(subject.admin_mode?).to be(false) - end + expect(subject.admin_mode?).to be(false) + end - it 'cannot be enabled with an invalid password' do - subject.enable_admin_mode!(password: nil) + it 'cannot be enabled with an invalid password' do + subject.enable_admin_mode!(password: nil) - expect(subject.admin_mode?).to be(false) - end + expect(subject.admin_mode?).to be(false) + end - it 'cannot be enabled with empty params' do - subject.enable_admin_mode! + it 'cannot be enabled with empty params' do + subject.enable_admin_mode! - expect(subject.admin_mode?).to be(false) - end + expect(subject.admin_mode?).to be(false) + end - it 'disable has no effect' do - subject.enable_admin_mode! - subject.disable_admin_mode! + it 'disable has no effect' do + subject.enable_admin_mode! + subject.disable_admin_mode! + + expect(subject.admin_mode?).to be(false) + end + + context 'skipping password validation' do + it 'cannot be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password, skip_password_validation: true) expect(subject.admin_mode?).to be(false) end - context 'skipping password validation' do - it 'cannot be enabled with a valid password' do - subject.enable_admin_mode!(password: user.password, skip_password_validation: true) + it 'cannot be enabled with an invalid password' do + subject.enable_admin_mode!(skip_password_validation: true) - expect(subject.admin_mode?).to be(false) - end + expect(subject.admin_mode?).to be(false) + end + end + end - it 'cannot be enabled with an invalid password' do - subject.enable_admin_mode!(skip_password_validation: true) + describe '#admin_mode?' do + context 'when the user is a regular user' do + it_behaves_like 'admin mode cannot be enabled' - expect(subject.admin_mode?).to be(false) + context 'bypassing session' do + it_behaves_like 'admin mode cannot be enabled' do + around do |example| + described_class.bypass_session!(user.id) { example.run } + end end end end context 'when the user is an admin' do - let(:user) { build(:user, :admin) } + let(:user) { build_stubbed(:user, :admin) } context 'when admin mode not requested' do it 'is false by default' do @@ -148,11 +160,36 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do end end end + + context 'bypassing session' do + it 'is active by default' do + described_class.bypass_session!(user.id) do + expect(subject.admin_mode?).to be(true) + end + end + + it 'enable has no effect' do + described_class.bypass_session!(user.id) do + subject.request_admin_mode! + subject.enable_admin_mode!(password: user.password) + + expect(subject.admin_mode?).to be(true) + end + end + + it 'disable has no effect' do + described_class.bypass_session!(user.id) do + subject.disable_admin_mode! + + expect(subject.admin_mode?).to be(true) + end + end + end end end describe '#enable_admin_mode!' do - let(:user) { build(:user, :admin) } + let(:user) { build_stubbed(:user, :admin) } it 'creates a timestamp in the session' do subject.request_admin_mode! @@ -163,7 +200,7 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do end describe '#enable_sessionless_admin_mode!' do - let(:user) { build(:user, :admin) } + let(:user) { build_stubbed(:user, :admin) } it 'enabled admin mode without password' do subject.enable_sessionless_admin_mode! @@ -173,7 +210,7 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do end describe '#disable_admin_mode!' do - let(:user) { build(:user, :admin) } + let(:user) { build_stubbed(:user, :admin) } it 'sets the session timestamp to nil' do subject.request_admin_mode! @@ -183,6 +220,73 @@ describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do end end + describe '.bypass_session!' do + context 'with a regular user' do + it 'admin mode is false' do + described_class.bypass_session!(user.id) do + expect(subject.admin_mode?).to be(false) + expect(described_class.bypass_session_admin_id).to be(user.id) + end + + expect(described_class.bypass_session_admin_id).to be_nil + end + end + + context 'with an admin user' do + let(:user) { build_stubbed(:user, :admin) } + + it 'admin mode is true' do + described_class.bypass_session!(user.id) do + expect(subject.admin_mode?).to be(true) + expect(described_class.bypass_session_admin_id).to be(user.id) + end + + expect(described_class.bypass_session_admin_id).to be_nil + end + end + end + + describe '.with_current_request_admin_mode' do + context 'with a regular user' do + it 'user is not available inside nor outside the yielded block' do + described_class.with_current_admin(user) do + expect(described_class.current_admin).to be_nil + end + + expect(described_class.bypass_session_admin_id).to be_nil + end + end + + context 'with an admin user' do + let(:user) { build_stubbed(:user, :admin) } + + context 'admin mode is disabled' do + it 'user is not available inside nor outside the yielded block' do + described_class.with_current_admin(user) do + expect(described_class.current_admin).to be_nil + end + + expect(described_class.bypass_session_admin_id).to be_nil + end + end + + context 'admin mode is enabled' do + before do + subject.request_admin_mode! + subject.enable_admin_mode!(password: user.password) + end + + it 'user is available only inside the yielded block' do + described_class.with_current_admin(user) do + expect(described_class.current_admin).to be(user) + end + + expect(described_class.current_admin).to be_nil + end + end + end + end + def expected_session_entry(value_matcher) { Gitlab::Auth::CurrentUserMode::SESSION_STORE_KEY => a_hash_including( diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb new file mode 100644 index 00000000000..f6449bae8c3 --- /dev/null +++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/client_spec.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::SidekiqMiddleware::AdminMode::Client, :do_not_mock_admin_mode, :request_store do + include AdminModeHelper + + let(:worker) do + Class.new do + def perform; end + end + end + + let(:job) { {} } + let(:queue) { :test } + + it 'yields block' do + expect do |b| + subject.call(worker, job, queue, nil, &b) + end.to yield_control.once + end + + context 'user is a regular user' do + it 'no admin mode field in payload' do + subject.call(worker, job, queue, nil) { nil } + + expect(job).not_to include('admin_mode_user_id') + end + end + + context 'user is an administrator' do + let(:admin) { create(:admin) } + + context 'admin mode disabled' do + it 'no admin mode field in payload' do + subject.call(worker, job, queue, nil) { nil } + + expect(job).not_to include('admin_mode_user_id') + end + end + + context 'admin mode enabled' do + before do + enable_admin_mode!(admin) + end + + context 'when sidekiq required context not set' do + it 'no admin mode field in payload' do + subject.call(worker, job, queue, nil) { nil } + + expect(job).not_to include('admin_mode_user_id') + end + end + + context 'when user stored in current request' do + it 'has admin mode field in payload' do + Gitlab::Auth::CurrentUserMode.with_current_admin(admin) do + subject.call(worker, job, queue, nil) { nil } + + expect(job).to include('admin_mode_user_id' => admin.id) + end + end + end + + context 'when bypassing session' do + it 'has admin mode field in payload' do + Gitlab::Auth::CurrentUserMode.bypass_session!(admin.id) do + subject.call(worker, job, queue, nil) { nil } + + expect(job).to include('admin_mode_user_id' => admin.id) + end + end + end + end + end + + context 'admin mode feature disabled' do + before do + stub_feature_flags(user_mode_in_session: false) + end + + it 'yields block' do + expect do |b| + subject.call(worker, job, queue, nil, &b) + end.to yield_control.once + end + + it 'no admin mode field in payload' do + subject.call(worker, job, queue, nil) { nil } + + expect(job).not_to include('admin_mode_user_id') + end + end +end diff --git a/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb new file mode 100644 index 00000000000..60475f0e403 --- /dev/null +++ b/spec/lib/gitlab/sidekiq_middleware/admin_mode/server_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::SidekiqMiddleware::AdminMode::Server, :do_not_mock_admin_mode, :request_store do + include AdminModeHelper + + let(:worker) do + Class.new do + def perform; end + end + end + + let(:job) { {} } + let(:queue) { :test } + + it 'yields block' do + expect do |b| + subject.call(worker, job, queue, &b) + end.to yield_control.once + end + + context 'job has no admin mode field' do + it 'session is not bypassed' do + subject.call(worker, job, queue) do + expect(Gitlab::Auth::CurrentUserMode.bypass_session_admin_id).to be_nil + end + end + end + + context 'job has admin mode field' do + let(:admin) { create(:admin) } + + context 'nil admin mode id' do + let(:job) { { 'admin_mode_user_id' => nil } } + + it 'session is not bypassed' do + subject.call(worker, job, queue) do + expect(Gitlab::Auth::CurrentUserMode.bypass_session_admin_id).to be_nil + end + end + end + + context 'valid admin mode id' do + let(:job) { { 'admin_mode_user_id' => admin.id } } + + it 'session is bypassed' do + subject.call(worker, job, queue) do + expect(Gitlab::Auth::CurrentUserMode.bypass_session_admin_id).to be(admin.id) + end + end + end + end + + context 'admin mode feature disabled' do + before do + stub_feature_flags(user_mode_in_session: false) + end + + it 'yields block' do + expect do |b| + subject.call(worker, job, queue, &b) + end.to yield_control.once + end + + it 'session is not bypassed' do + subject.call(worker, job, queue) do + expect(Gitlab::Auth::CurrentUserMode.bypass_session_admin_id).to be_nil + end + end + end +end diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb index e8dcbbd2ee1..19242d25e27 100644 --- a/spec/lib/gitlab/sidekiq_middleware_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb @@ -45,7 +45,8 @@ describe Gitlab::SidekiqMiddleware do Gitlab::SidekiqMiddleware::ArgumentsLogger, Gitlab::SidekiqMiddleware::MemoryKiller, Gitlab::SidekiqMiddleware::RequestStoreMiddleware, - Gitlab::SidekiqMiddleware::WorkerContext::Server + Gitlab::SidekiqMiddleware::WorkerContext::Server, + Gitlab::SidekiqMiddleware::AdminMode::Server ] end let(:enabled_sidekiq_middlewares) { all_sidekiq_middlewares - disabled_sidekiq_middlewares } @@ -115,7 +116,8 @@ describe Gitlab::SidekiqMiddleware do Gitlab::SidekiqStatus::ClientMiddleware, Gitlab::SidekiqMiddleware::ClientMetrics, Gitlab::SidekiqMiddleware::WorkerContext::Client, - Labkit::Middleware::Sidekiq::Client + Labkit::Middleware::Sidekiq::Client, + Gitlab::SidekiqMiddleware::AdminMode::Client ] end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f2b95e00b5e..74e38e79616 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2985,9 +2985,9 @@ describe User, :do_not_mock_admin_mode do end end - describe '#can_read_all_resources?' do + describe '#can_read_all_resources?', :request_store do it 'returns false for regular user' do - user = build(:user) + user = build_stubbed(:user) expect(user.can_read_all_resources?).to be_falsy end @@ -2995,7 +2995,7 @@ describe User, :do_not_mock_admin_mode do context 'for admin user' do include_context 'custom session' - let(:user) { build(:user, :admin) } + let(:user) { build_stubbed(:user, :admin) } context 'when admin mode is disabled' do it 'returns false' do diff --git a/spec/policies/base_policy_spec.rb b/spec/policies/base_policy_spec.rb index 81aee4cfcac..ae5af9e0f29 100644 --- a/spec/policies/base_policy_spec.rb +++ b/spec/policies/base_policy_spec.rb @@ -23,8 +23,8 @@ describe BasePolicy, :do_not_mock_admin_mode do end describe 'read cross project' do - let(:current_user) { create(:user) } - let(:user) { create(:user) } + let(:current_user) { build_stubbed(:user) } + let(:user) { build_stubbed(:user) } subject { described_class.new(current_user, [user]) } @@ -38,7 +38,7 @@ describe BasePolicy, :do_not_mock_admin_mode do it { is_expected.not_to be_allowed(:read_cross_project) } context 'for admins' do - let(:current_user) { build(:admin) } + let(:current_user) { build_stubbed(:admin) } subject { described_class.new(current_user, nil) } @@ -56,14 +56,14 @@ describe BasePolicy, :do_not_mock_admin_mode do end describe 'full private access' do - let(:current_user) { create(:user) } + let(:current_user) { build_stubbed(:user) } subject { described_class.new(current_user, nil) } it { is_expected.not_to be_allowed(:read_all_resources) } context 'for admins' do - let(:current_user) { build(:admin) } + let(:current_user) { build_stubbed(:admin) } it 'allowed when in admin mode' do enable_admin_mode!(current_user) diff --git a/spec/requests/api/error_tracking_spec.rb b/spec/requests/api/error_tracking_spec.rb index 48ddc7f5a75..059744898b8 100644 --- a/spec/requests/api/error_tracking_spec.rb +++ b/spec/requests/api/error_tracking_spec.rb @@ -3,11 +3,129 @@ require 'spec_helper' describe API::ErrorTracking do - describe "GET /projects/:id/error_tracking/settings" do - let(:user) { create(:user) } - let(:setting) { create(:project_error_tracking_setting) } - let(:project) { setting.project } + let(:user) { create(:user) } + let(:setting) { create(:project_error_tracking_setting) } + let(:project) { setting.project } + + shared_examples 'returns project settings' do + it 'returns correct project settings' do + subject + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to eq( + 'active' => setting.reload.enabled, + 'project_name' => setting.project_name, + 'sentry_external_url' => setting.sentry_external_url, + 'api_url' => setting.api_url + ) + end + end + + shared_examples 'returns 404' do + it 'returns correct project settings' do + subject + + expect(response).to have_gitlab_http_status(:not_found) + expect(json_response['message']) + .to eq('404 Error Tracking Setting Not Found') + end + end + + describe "PATCH /projects/:id/error_tracking/settings" do + def make_patch_request(**params) + patch api("/projects/#{project.id}/error_tracking/settings", user), params: params + end + + context 'when authenticated as maintainer' do + before do + project.add_maintainer(user) + end + + context 'patch settings' do + subject do + make_patch_request(active: false) + end + + it_behaves_like 'returns project settings' + + it 'returns active is invalid if non boolean' do + make_patch_request(active: "randomstring") + + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['error']) + .to eq('active is invalid') + end + + it 'returns 400 if active is empty' do + make_patch_request(active: '') + expect(response).to have_gitlab_http_status(:bad_request) + expect(json_response['error']) + .to eq('active is empty') + end + end + + context 'without a project setting' do + let(:project) { create(:project) } + + before do + project.add_maintainer(user) + end + + context 'patch settings' do + subject do + make_patch_request(active: true) + end + + it_behaves_like 'returns 404' + end + end + end + + context 'when authenticated as reporter' do + before do + project.add_reporter(user) + end + + it 'returns 403 for update request' do + make_patch_request(active: true) + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when authenticated as developer' do + before do + project.add_developer(user) + end + + it 'returns 403 for update request' do + make_patch_request(active: true) + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + + context 'when authenticated as non-member' do + it 'returns 404 for update request' do + make_patch_request(active: false) + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when unauthenticated' do + let(:user) { nil } + + it 'returns 401 for update request' do + make_patch_request(active: true) + + expect(response).to have_gitlab_http_status(:unauthorized) + end + end + end + + describe "GET /projects/:id/error_tracking/settings" do def make_request get api("/projects/#{project.id}/error_tracking/settings", user) end @@ -17,16 +135,12 @@ describe API::ErrorTracking do project.add_maintainer(user) end - it 'returns project settings' do - make_request + context 'get settings' do + subject do + make_request + end - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to eq( - 'active' => setting.enabled, - 'project_name' => setting.project_name, - 'sentry_external_url' => setting.sentry_external_url, - 'api_url' => setting.api_url - ) + it_behaves_like 'returns project settings' end end @@ -37,12 +151,12 @@ describe API::ErrorTracking do project.add_maintainer(user) end - it 'returns 404' do - make_request + context 'get settings' do + subject do + make_request + end - expect(response).to have_gitlab_http_status(:not_found) - expect(json_response['message']) - .to eq('404 Error Tracking Setting Not Found') + it_behaves_like 'returns 404' end end @@ -58,6 +172,18 @@ describe API::ErrorTracking do end end + context 'when authenticated as developer' do + before do + project.add_developer(user) + end + + it 'returns 403' do + make_request + + expect(response).to have_gitlab_http_status(:forbidden) + end + end + context 'when authenticated as non-member' do it 'returns 404' do make_request diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb index a3538aa98b1..09e005398a9 100644 --- a/spec/requests/api/issues/issues_spec.rb +++ b/spec/requests/api/issues/issues_spec.rb @@ -778,6 +778,32 @@ describe API::Issues do expect(json_response["error"]).to include("mutually exclusive") end end + + context 'filtering by non_archived' do + let_it_be(:group1) { create(:group) } + let_it_be(:archived_project) { create(:project, :archived, namespace: group1) } + let_it_be(:active_project) { create(:project, namespace: group1) } + let_it_be(:issue1) { create(:issue, project: active_project) } + let_it_be(:issue2) { create(:issue, project: active_project) } + let_it_be(:issue3) { create(:issue, project: archived_project) } + + before do + archived_project.add_developer(user) + active_project.add_developer(user) + end + + it 'returns issues from non archived projects only by default' do + get api("/groups/#{group1.id}/issues", user), params: { scope: 'all' } + + expect_response_contain_exactly(issue2, issue1) + end + + it 'returns issues from archived and non archived projects when non_archived is false' do + get api("/groups/#{group1.id}/issues", user), params: { non_archived: false, scope: 'all' } + + expect_response_contain_exactly(issue1, issue2, issue3) + end + end end context "when returns issue merge_requests_count for different access levels" do @@ -862,4 +888,9 @@ describe API::Issues do include_examples 'time tracking endpoints', 'issue' end + + def expect_response_contain_exactly(*items) + expect(json_response.length).to eq(items.size) + expect(json_response.map { |element| element['id'] }).to contain_exactly(*items.map(&:id)) + end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 33ac175e945..adfe865da90 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -807,6 +807,38 @@ describe API::MergeRequests do end end end + + context 'with archived projects' do + let(:project2) { create(:project, :public, :archived, namespace: group) } + let!(:merge_request_archived) { create(:merge_request, title: 'archived mr', author: user, source_project: project2, target_project: project2) } + + it 'returns an array excluding merge_requests from archived projects' do + get api(endpoint_path, user) + + expect_response_contain_exactly( + merge_request_merged, + merge_request_locked, + merge_request_closed, + merge_request + ) + end + + context 'with non_archived param set as false' do + it 'returns an array including merge_requests from archived projects' do + path = endpoint_path + '?non_archived=false' + + get api(path, user) + + expect_response_contain_exactly( + merge_request_merged, + merge_request_locked, + merge_request_closed, + merge_request, + merge_request_archived + ) + end + end + end end describe "GET /projects/:id/merge_requests/:merge_request_iid" do diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb index d20ec0b818b..dce0ee05b1f 100644 --- a/spec/services/projects/operations/update_service_spec.rb +++ b/spec/services/projects/operations/update_service_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' describe Projects::Operations::UpdateService do let_it_be(:user) { create(:user) } - let_it_be(:project, reload: true) { create(:project) } + let_it_be(:project, refind: true) { create(:project) } let(:result) { subject.execute } @@ -145,6 +145,48 @@ describe Projects::Operations::UpdateService do end end + context 'partial_update' do + let(:params) do + { + error_tracking_setting_attributes: { + enabled: true + } + } + end + + context 'with setting' do + before do + create(:project_error_tracking_setting, :disabled, project: project) + end + + it 'service succeeds' do + expect(result[:status]).to eq(:success) + end + + it 'updates attributes' do + expect { result } + .to change { project.reload.error_tracking_setting.enabled } + .from(false) + .to(true) + end + + it 'only updates enabled attribute' do + result + + expect(project.error_tracking_setting.previous_changes.keys) + .to contain_exactly('enabled') + end + end + + context 'without setting' do + it 'does not create a setting' do + expect(result[:status]).to eq(:error) + + expect(project.reload.error_tracking_setting).to be_nil + end + end + end + context 'with masked param token' do let(:params) do { diff --git a/spec/support/helpers/controller_helpers.rb b/spec/support/helpers/controller_helpers.rb new file mode 100644 index 00000000000..8f5ef8c9696 --- /dev/null +++ b/spec/support/helpers/controller_helpers.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module ControllerHelpers + # It seems Devise::Test::ControllerHelpers#sign_in doesn't clear out the @current_user + # variable of the controller, hence it's not overwritten on retries. + # This should be fixed in Devise: + # - https://github.com/heartcombo/devise/issues/5190 + # - https://github.com/heartcombo/devise/pull/5191 + def sign_in(resource, deprecated = nil, scope: nil) + super + + scope ||= Devise::Mapping.find_scope!(resource) + + @controller.instance_variable_set(:"@current_#{scope}", nil) + end +end + +Devise::Test::ControllerHelpers.prepend(ControllerHelpers) |