diff options
Diffstat (limited to 'spec/frontend/jobs')
-rw-r--r-- | spec/frontend/jobs/components/empty_state_spec.js | 128 | ||||
-rw-r--r-- | spec/frontend/jobs/components/job_app_spec.js | 85 | ||||
-rw-r--r-- | spec/frontend/jobs/components/job_log_controllers_spec.js | 167 | ||||
-rw-r--r-- | spec/frontend/jobs/components/log/mock_data.js | 2 | ||||
-rw-r--r-- | spec/frontend/jobs/components/sidebar_spec.js | 6 | ||||
-rw-r--r-- | spec/frontend/jobs/components/stuck_block_spec.js | 68 |
6 files changed, 255 insertions, 201 deletions
diff --git a/spec/frontend/jobs/components/empty_state_spec.js b/spec/frontend/jobs/components/empty_state_spec.js index c6eac4e27b3..29d0c4e07aa 100644 --- a/spec/frontend/jobs/components/empty_state_spec.js +++ b/spec/frontend/jobs/components/empty_state_spec.js @@ -1,12 +1,10 @@ -import Vue from 'vue'; -import component from '~/jobs/components/empty_state.vue'; -import mountComponent from '../../helpers/vue_mount_component_helper'; +import { mount } from '@vue/test-utils'; +import EmptyState from '~/jobs/components/empty_state.vue'; describe('Empty State', () => { - const Component = Vue.extend(component); - let vm; + let wrapper; - const props = { + const defaultProps = { illustrationPath: 'illustrations/pending_job_empty.svg', illustrationSizeClass: 'svg-430', title: 'This job has not started yet', @@ -14,100 +12,107 @@ describe('Empty State', () => { variablesSettingsUrl: '', }; + const createWrapper = props => { + wrapper = mount(EmptyState, { + propsData: { + ...defaultProps, + ...props, + }, + }); + }; + const content = 'This job is in pending state and is waiting to be picked by a runner'; + const findEmptyStateImage = () => wrapper.find('img'); + const findTitle = () => wrapper.find('[data-testid="job-empty-state-title"]'); + const findContent = () => wrapper.find('[data-testid="job-empty-state-content"]'); + const findAction = () => wrapper.find('[data-testid="job-empty-state-action"]'); + const findManualVarsForm = () => wrapper.find('[data-testid="manual-vars-form"]'); + afterEach(() => { - vm.$destroy(); + if (wrapper?.destroy) { + wrapper.destroy(); + wrapper = null; + } }); describe('renders image and title', () => { beforeEach(() => { - vm = mountComponent(Component, { - ...props, - content, - }); + createWrapper(); }); - it('renders img with provided path and size', () => { - expect(vm.$el.querySelector('img').getAttribute('src')).toEqual(props.illustrationPath); - expect(vm.$el.querySelector('.svg-content').classList).toContain(props.illustrationSizeClass); + it('renders empty state image', () => { + expect(findEmptyStateImage().exists()).toBe(true); }); it('renders provided title', () => { - expect(vm.$el.querySelector('.js-job-empty-state-title').textContent.trim()).toEqual( - props.title, - ); + expect( + findTitle() + .text() + .trim(), + ).toBe(defaultProps.title); }); }); describe('with content', () => { - it('renders content', () => { - vm = mountComponent(Component, { - ...props, - content, - }); + beforeEach(() => { + createWrapper({ content }); + }); - expect(vm.$el.querySelector('.js-job-empty-state-content').textContent.trim()).toEqual( - content, - ); + it('renders content', () => { + expect( + findContent() + .text() + .trim(), + ).toBe(content); }); }); describe('without content', () => { - it('does not render content', () => { - vm = mountComponent(Component, { - ...props, - }); + beforeEach(() => { + createWrapper(); + }); - expect(vm.$el.querySelector('.js-job-empty-state-content')).toBeNull(); + it('does not render content', () => { + expect(findContent().exists()).toBe(false); }); }); describe('with action', () => { - it('renders action', () => { - vm = mountComponent(Component, { - ...props, - content, + beforeEach(() => { + createWrapper({ action: { path: 'runner', button_title: 'Check runner', method: 'post', }, }); + }); - expect(vm.$el.querySelector('.js-job-empty-state-action').getAttribute('href')).toEqual( - 'runner', - ); + it('renders action', () => { + expect(findAction().attributes('href')).toBe('runner'); }); }); describe('without action', () => { - it('does not render action', () => { - vm = mountComponent(Component, { - ...props, - content, + beforeEach(() => { + createWrapper({ action: null, }); + }); - expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull(); + it('does not render action', () => { + expect(findAction().exists()).toBe(false); }); - }); - describe('without playbale action', () => { it('does not render manual variables form', () => { - vm = mountComponent(Component, { - ...props, - content, - }); - - expect(vm.$el.querySelector('.js-manual-vars-form')).toBeNull(); + expect(findManualVarsForm().exists()).toBe(false); }); }); - describe('with playbale action and not scheduled job', () => { + describe('with playable action and not scheduled job', () => { beforeEach(() => { - vm = mountComponent(Component, { - ...props, + createWrapper({ content, playable: true, scheduled: false, @@ -120,22 +125,25 @@ describe('Empty State', () => { }); it('renders manual variables form', () => { - expect(vm.$el.querySelector('.js-manual-vars-form')).not.toBeNull(); + expect(findManualVarsForm().exists()).toBe(true); }); it('does not render the empty state action', () => { - expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull(); + expect(findAction().exists()).toBe(false); }); }); - describe('with playbale action and scheduled job', () => { - it('does not render manual variables form', () => { - vm = mountComponent(Component, { - ...props, + describe('with playable action and scheduled job', () => { + beforeEach(() => { + createWrapper({ + playable: true, + scheduled: true, content, }); + }); - expect(vm.$el.querySelector('.js-manual-vars-form')).toBeNull(); + it('does not render manual variables form', () => { + expect(findManualVarsForm().exists()).toBe(false); }); }); }); diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js index d0b3d4f6247..e9ecafcd4c3 100644 --- a/spec/frontend/jobs/components/job_app_spec.js +++ b/spec/frontend/jobs/components/job_app_spec.js @@ -1,12 +1,19 @@ import Vuex from 'vuex'; import { mount, createLocalVue } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import { getJSONFixture } from 'helpers/fixtures'; +import { TEST_HOST } from 'jest/helpers/test_constants'; import axios from '~/lib/utils/axios_utils'; import JobApp from '~/jobs/components/job_app.vue'; +import Sidebar from '~/jobs/components/sidebar.vue'; +import StuckBlock from '~/jobs/components/stuck_block.vue'; +import UnmetPrerequisitesBlock from '~/jobs/components/unmet_prerequisites_block.vue'; +import EnvironmentsBlock from '~/jobs/components/environments_block.vue'; +import ErasedBlock from '~/jobs/components/erased_block.vue'; +import EmptyState from '~/jobs/components/empty_state.vue'; import createStore from '~/jobs/store'; import job from '../mock_data'; -import { TEST_HOST } from 'jest/helpers/test_constants'; describe('Job App', () => { const localVue = createLocalVue(); @@ -55,6 +62,26 @@ describe('Job App', () => { .then(() => wrapper.vm.$nextTick()); }; + const findLoadingComponent = () => wrapper.find(GlLoadingIcon); + const findSidebar = () => wrapper.find(Sidebar); + const findJobContent = () => wrapper.find('[data-testid="job-content"'); + const findStuckBlockComponent = () => wrapper.find(StuckBlock); + const findStuckBlockWithTags = () => wrapper.find('[data-testid="job-stuck-with-tags"'); + const findStuckBlockNoActiveRunners = () => + wrapper.find('[data-testid="job-stuck-no-active-runners"'); + const findFailedJobComponent = () => wrapper.find(UnmetPrerequisitesBlock); + const findEnvironmentsBlockComponent = () => wrapper.find(EnvironmentsBlock); + const findErasedBlock = () => wrapper.find(ErasedBlock); + const findArchivedJob = () => wrapper.find('[data-testid="archived-job"]'); + const findEmptyState = () => wrapper.find(EmptyState); + const findJobNewIssueLink = () => wrapper.find('[data-testid="job-new-issue"]'); + const findJobEmptyStateTitle = () => wrapper.find('[data-testid="job-empty-state-title"]'); + const findJobTraceScrollTop = () => wrapper.find('[data-testid="job-controller-scroll-top"]'); + const findJobTraceScrollBottom = () => + wrapper.find('[data-testid="job-controller-scroll-bottom"]'); + const findJobTraceController = () => wrapper.find('[data-testid="job-raw-link-controller"]'); + const findJobTraceEraseLink = () => wrapper.find('[data-testid="job-log-erase-link"]'); + beforeEach(() => { mock = new MockAdapter(axios); store = createStore(); @@ -72,9 +99,9 @@ describe('Job App', () => { }); it('renders loading icon', () => { - 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); + expect(findLoadingComponent().exists()).toBe(true); + expect(findSidebar().exists()).toBe(false); + expect(findJobContent().exists()).toBe(false); }); }); @@ -115,7 +142,7 @@ describe('Job App', () => { }); it('should render new issue link', () => { - expect(wrapper.find('.js-new-issue').attributes('href')).toEqual(job.new_issue_path); + expect(findJobNewIssueLink().attributes('href')).toEqual(job.new_issue_path); }); }); @@ -134,7 +161,7 @@ describe('Job App', () => { }); describe('stuck block', () => { - describe('without active runners availabl', () => { + describe('without active runners available', () => { it('renders stuck block when there are no runners', () => setupAndMount({ jobData: { @@ -153,8 +180,8 @@ describe('Job App', () => { tags: [], }, }).then(() => { - expect(wrapper.find('.js-job-stuck').exists()).toBe(true); - expect(wrapper.find('.js-job-stuck .js-stuck-no-active-runner').exists()).toBe(true); + expect(findStuckBlockComponent().exists()).toBe(true); + expect(findStuckBlockNoActiveRunners().exists()).toBe(true); })); }); @@ -176,8 +203,8 @@ describe('Job App', () => { }, }, }).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); + expect(findStuckBlockComponent().text()).toContain(job.tags[0]); + expect(findStuckBlockWithTags().exists()).toBe(true); })); }); @@ -199,8 +226,8 @@ describe('Job App', () => { }, }, }).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); + expect(findStuckBlockComponent().text()).toContain(job.tags[0]); + expect(findStuckBlockWithTags().exists()).toBe(true); })); }); @@ -210,7 +237,7 @@ describe('Job App', () => { runners: { available: true }, }, }).then(() => { - expect(wrapper.find('.js-job-stuck').exists()).toBe(false); + expect(findStuckBlockComponent().exists()).toBe(false); })); }); @@ -239,7 +266,7 @@ describe('Job App', () => { tags: [], }, }).then(() => { - expect(wrapper.find('.js-job-failed').exists()).toBe(true); + expect(findFailedJobComponent().exists()).toBe(true); })); }); @@ -255,12 +282,12 @@ describe('Job App', () => { }, }, }).then(() => { - expect(wrapper.find('.js-job-environment').exists()).toBe(true); + expect(findEnvironmentsBlockComponent().exists()).toBe(true); })); it('does not render environment block when job has environment', () => setupAndMount().then(() => { - expect(wrapper.find('.js-job-environment').exists()).toBe(false); + expect(findEnvironmentsBlockComponent().exists()).toBe(false); })); }); @@ -275,7 +302,7 @@ describe('Job App', () => { erased_at: '2016-11-07T11:11:16.525Z', }, }).then(() => { - expect(wrapper.find('.js-job-erased-block').exists()).toBe(true); + expect(findErasedBlock().exists()).toBe(true); })); it('does not render erased block when `erased` is false', () => @@ -284,7 +311,7 @@ describe('Job App', () => { erased_at: null, }, }).then(() => { - expect(wrapper.find('.js-job-erased-block').exists()).toBe(false); + expect(findErasedBlock().exists()).toBe(false); })); }); @@ -313,7 +340,7 @@ describe('Job App', () => { }, }, }).then(() => { - expect(wrapper.find('.js-job-empty-state').exists()).toBe(true); + expect(findEmptyState().exists()).toBe(true); })); it('does not render empty state when job does not have trace but it is running', () => @@ -329,12 +356,12 @@ describe('Job App', () => { }, }, }).then(() => { - expect(wrapper.find('.js-job-empty-state').exists()).toBe(false); + expect(findEmptyState().exists()).toBe(false); })); 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); + expect(findEmptyState().exists()).toBe(false); })); it('displays remaining time for a delayed job', () => { @@ -345,9 +372,9 @@ describe('Job App', () => { () => new Date(delayedJobFixture.scheduled_at).getTime() - oneHourInMilliseconds, ); return setupAndMount({ jobData: delayedJobFixture }).then(() => { - expect(wrapper.find('.js-job-empty-state').exists()).toBe(true); + expect(findEmptyState().exists()).toBe(true); - const title = wrapper.find('.js-job-empty-state-title').text(); + const title = findJobEmptyStateTitle().text(); expect(title).toEqual('This is a delayed job to run in 01:00:00'); }); @@ -386,7 +413,7 @@ describe('Job App', () => { beforeEach(() => setupAndMount({ jobData: { archived: true } })); it('renders warning about job being archived', () => { - expect(wrapper.find('.js-archived-job ').exists()).toBe(true); + expect(findArchivedJob().exists()).toBe(true); }); }); @@ -394,7 +421,7 @@ describe('Job App', () => { beforeEach(() => setupAndMount()); it('does not warning about job being archived', () => { - expect(wrapper.find('.js-archived-job ').exists()).toBe(false); + expect(findArchivedJob().exists()).toBe(false); }); }); @@ -413,16 +440,16 @@ describe('Job App', () => { ); it('should render scroll buttons', () => { - expect(wrapper.find('.js-scroll-top').exists()).toBe(true); - expect(wrapper.find('.js-scroll-bottom').exists()).toBe(true); + expect(findJobTraceScrollTop().exists()).toBe(true); + expect(findJobTraceScrollBottom().exists()).toBe(true); }); it('should render link to raw ouput', () => { - expect(wrapper.find('.js-raw-link-controller').exists()).toBe(true); + expect(findJobTraceController().exists()).toBe(true); }); it('should render link to erase job', () => { - expect(wrapper.find('.js-erase-link').exists()).toBe(true); + expect(findJobTraceEraseLink().exists()).toBe(true); }); }); }); diff --git a/spec/frontend/jobs/components/job_log_controllers_spec.js b/spec/frontend/jobs/components/job_log_controllers_spec.js index 04f20811601..233cef05622 100644 --- a/spec/frontend/jobs/components/job_log_controllers_spec.js +++ b/spec/frontend/jobs/components/job_log_controllers_spec.js @@ -1,16 +1,17 @@ -import Vue from 'vue'; -import component from '~/jobs/components/job_log_controllers.vue'; -import mountComponent from '../../helpers/vue_mount_component_helper'; +import { mount } from '@vue/test-utils'; +import JobLogControllers from '~/jobs/components/job_log_controllers.vue'; describe('Job log controllers', () => { - const Component = Vue.extend(component); - let vm; + let wrapper; afterEach(() => { - vm.$destroy(); + if (wrapper?.destroy) { + wrapper.destroy(); + wrapper = null; + } }); - const props = { + const defaultProps = { rawPath: '/raw', erasePath: '/erase', size: 511952, @@ -20,70 +21,80 @@ describe('Job log controllers', () => { isTraceSizeVisible: true, }; + const createWrapper = props => { + wrapper = mount(JobLogControllers, { + propsData: { + ...defaultProps, + ...props, + }, + }); + }; + + const findTruncatedInfo = () => wrapper.find('[data-testid="log-truncated-info"]'); + const findRawLink = () => wrapper.find('[data-testid="raw-link"]'); + const findRawLinkController = () => wrapper.find('[data-testid="job-raw-link-controller"]'); + const findEraseLink = () => wrapper.find('[data-testid="job-log-erase-link"]'); + const findScrollTop = () => wrapper.find('[data-testid="job-controller-scroll-top"]'); + const findScrollBottom = () => wrapper.find('[data-testid="job-controller-scroll-bottom"]'); + describe('Truncate information', () => { describe('with isTraceSizeVisible', () => { beforeEach(() => { - vm = mountComponent(Component, props); + createWrapper(); }); it('renders size information', () => { - expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB'); + expect(findTruncatedInfo().text()).toMatch('499.95 KiB'); }); it('renders link to raw trace', () => { - expect(vm.$el.querySelector('.js-raw-link').getAttribute('href')).toEqual('/raw'); + expect(findRawLink().attributes('href')).toBe(defaultProps.rawPath); }); }); }); describe('links section', () => { describe('with raw trace path', () => { - it('renders raw trace link', () => { - vm = mountComponent(Component, props); + beforeEach(() => { + createWrapper(); + }); - expect(vm.$el.querySelector('.js-raw-link-controller').getAttribute('href')).toEqual( - '/raw', - ); + it('renders raw trace link', () => { + expect(findRawLinkController().attributes('href')).toBe(defaultProps.rawPath); }); }); describe('without raw trace path', () => { - it('does not render raw trace link', () => { - vm = mountComponent(Component, { - erasePath: '/erase', - size: 511952, - isScrollTopDisabled: true, - isScrollBottomDisabled: true, - isScrollingDown: false, - isTraceSizeVisible: true, + beforeEach(() => { + createWrapper({ + rawPath: null, }); + }); - expect(vm.$el.querySelector('.js-raw-link-controller')).toBeNull(); + it('does not render raw trace link', () => { + expect(findRawLinkController().exists()).toBe(false); }); }); describe('when is erasable', () => { beforeEach(() => { - vm = mountComponent(Component, props); + createWrapper(); }); it('renders erase job link', () => { - expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull(); + expect(findEraseLink().exists()).toBe(true); }); }); describe('when it is not erasable', () => { - it('does not render erase button', () => { - vm = mountComponent(Component, { - rawPath: '/raw', - size: 511952, - isScrollTopDisabled: true, - isScrollBottomDisabled: true, - isScrollingDown: false, - isTraceSizeVisible: true, + beforeEach(() => { + createWrapper({ + erasePath: null, }); + }); - expect(vm.$el.querySelector('.js-erase-link')).toBeNull(); + it('does not render erase button', () => { + expect(findEraseLink().exists()).toBe(false); }); }); }); @@ -92,45 +103,39 @@ describe('Job log controllers', () => { describe('scroll top button', () => { describe('when user can scroll top', () => { beforeEach(() => { - vm = mountComponent(Component, props); + createWrapper({ + isScrollTopDisabled: false, + }); }); - it('renders enabled scroll top button', () => { - expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toBeNull(); - }); + it('emits scrollJobLogTop event on click', async () => { + findScrollTop().trigger('click'); - it('emits scrollJobLogTop event on click', () => { - jest.spyOn(vm, '$emit').mockImplementation(() => {}); - vm.$el.querySelector('.js-scroll-top').click(); + await wrapper.vm.$nextTick(); - expect(vm.$emit).toHaveBeenCalledWith('scrollJobLogTop'); + expect(wrapper.emitted().scrollJobLogTop).toHaveLength(1); }); }); describe('when user can not scroll top', () => { beforeEach(() => { - vm = mountComponent(Component, { - rawPath: '/raw', - erasePath: '/erase', - size: 511952, + createWrapper({ isScrollTopDisabled: true, isScrollBottomDisabled: false, isScrollingDown: false, - isTraceSizeVisible: true, }); }); it('renders disabled scroll top button', () => { - expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toEqual( - 'disabled', - ); + expect(findScrollTop().attributes('disabled')).toBe('disabled'); }); - it('does not emit scrollJobLogTop event on click', () => { - jest.spyOn(vm, '$emit').mockImplementation(() => {}); - vm.$el.querySelector('.js-scroll-top').click(); + it('does not emit scrollJobLogTop event on click', async () => { + findScrollTop().trigger('click'); - expect(vm.$emit).not.toHaveBeenCalledWith('scrollJobLogTop'); + await wrapper.vm.$nextTick(); + + expect(wrapper.emitted().scrollJobLogTop).toBeUndefined(); }); }); }); @@ -138,69 +143,61 @@ describe('Job log controllers', () => { describe('scroll bottom button', () => { describe('when user can scroll bottom', () => { beforeEach(() => { - vm = mountComponent(Component, props); + createWrapper(); }); - it('renders enabled scroll bottom button', () => { - expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toBeNull(); - }); + it('emits scrollJobLogBottom event on click', async () => { + findScrollBottom().trigger('click'); - it('emits scrollJobLogBottom event on click', () => { - jest.spyOn(vm, '$emit').mockImplementation(() => {}); - vm.$el.querySelector('.js-scroll-bottom').click(); + await wrapper.vm.$nextTick(); - expect(vm.$emit).toHaveBeenCalledWith('scrollJobLogBottom'); + expect(wrapper.emitted().scrollJobLogBottom).toHaveLength(1); }); }); describe('when user can not scroll bottom', () => { beforeEach(() => { - vm = mountComponent(Component, { - rawPath: '/raw', - erasePath: '/erase', - size: 511952, + createWrapper({ isScrollTopDisabled: false, isScrollBottomDisabled: true, isScrollingDown: false, - isTraceSizeVisible: true, }); }); it('renders disabled scroll bottom button', () => { - expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toEqual( - 'disabled', - ); + expect(findScrollBottom().attributes('disabled')).toEqual('disabled'); }); - it('does not emit scrollJobLogBottom event on click', () => { - jest.spyOn(vm, '$emit').mockImplementation(() => {}); - vm.$el.querySelector('.js-scroll-bottom').click(); + it('does not emit scrollJobLogBottom event on click', async () => { + findScrollBottom().trigger('click'); - expect(vm.$emit).not.toHaveBeenCalledWith('scrollJobLogBottom'); + await wrapper.vm.$nextTick(); + + expect(wrapper.emitted().scrollJobLogBottom).toBeUndefined(); }); }); describe('while isScrollingDown is true', () => { - it('renders animate class for the scroll down button', () => { - vm = mountComponent(Component, props); + beforeEach(() => { + createWrapper(); + }); - expect(vm.$el.querySelector('.js-scroll-bottom').className).toContain('animate'); + it('renders animate class for the scroll down button', () => { + expect(findScrollBottom().classes()).toContain('animate'); }); }); describe('while isScrollingDown is false', () => { - it('does not render animate class for the scroll down button', () => { - vm = mountComponent(Component, { - rawPath: '/raw', - erasePath: '/erase', - size: 511952, + beforeEach(() => { + createWrapper({ isScrollTopDisabled: true, isScrollBottomDisabled: false, isScrollingDown: false, - isTraceSizeVisible: true, }); + }); - expect(vm.$el.querySelector('.js-scroll-bottom').className).not.toContain('animate'); + it('does not render animate class for the scroll down button', () => { + expect(findScrollBottom().classes()).not.toContain('animate'); }); }); }); diff --git a/spec/frontend/jobs/components/log/mock_data.js b/spec/frontend/jobs/components/log/mock_data.js index a6a767f7921..eb8c4fe8bc9 100644 --- a/spec/frontend/jobs/components/log/mock_data.js +++ b/spec/frontend/jobs/components/log/mock_data.js @@ -34,7 +34,7 @@ export const utilsMockData = [ content: [ { text: - 'Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.27-lfs-2.9-chrome-83-node-12.x-yarn-1.21-postgresql-11-graphicsmagick-1.3.34', + 'Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.6-golang-1.14-git-2.28-lfs-2.9-chrome-84-node-12.x-yarn-1.21-postgresql-11-graphicsmagick-1.3.34', }, ], section: 'prepare-executor', diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js index 0c8e2dc3aef..48788df0c93 100644 --- a/spec/frontend/jobs/components/sidebar_spec.js +++ b/spec/frontend/jobs/components/sidebar_spec.js @@ -59,11 +59,13 @@ describe('Sidebar details block', () => { describe('actions', () => { it('should render link to new issue', () => { - expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual( + expect(vm.$el.querySelector('[data-testid="job-new-issue"]').getAttribute('href')).toEqual( job.new_issue_path, ); - expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue'); + expect(vm.$el.querySelector('[data-testid="job-new-issue"]').textContent.trim()).toEqual( + 'New issue', + ); }); it('should render link to retry job', () => { diff --git a/spec/frontend/jobs/components/stuck_block_spec.js b/spec/frontend/jobs/components/stuck_block_spec.js index c320793b2be..926286bf75a 100644 --- a/spec/frontend/jobs/components/stuck_block_spec.js +++ b/spec/frontend/jobs/components/stuck_block_spec.js @@ -1,31 +1,50 @@ -import Vue from 'vue'; -import component from '~/jobs/components/stuck_block.vue'; -import mountComponent from '../../helpers/vue_mount_component_helper'; +import { GlBadge, GlLink } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import StuckBlock from '~/jobs/components/stuck_block.vue'; describe('Stuck Block Job component', () => { - const Component = Vue.extend(component); - let vm; + let wrapper; afterEach(() => { - vm.$destroy(); + if (wrapper?.destroy) { + wrapper.destroy(); + wrapper = null; + } }); + const createWrapper = props => { + wrapper = shallowMount(StuckBlock, { + propsData: { + ...props, + }, + }); + }; + + const tags = ['docker', 'gitlab-org']; + + const findStuckNoActiveRunners = () => + wrapper.find('[data-testid="job-stuck-no-active-runners"]'); + const findStuckNoRunners = () => wrapper.find('[data-testid="job-stuck-no-runners"]'); + const findStuckWithTags = () => wrapper.find('[data-testid="job-stuck-with-tags"]'); + const findRunnerPathLink = () => wrapper.find(GlLink); + const findAllBadges = () => wrapper.findAll(GlBadge); + describe('with no runners for project', () => { beforeEach(() => { - vm = mountComponent(Component, { + createWrapper({ hasNoRunnersForProject: true, runnersPath: '/root/project/runners#js-runners-settings', }); }); it('renders only information about project not having runners', () => { - expect(vm.$el.querySelector('.js-stuck-no-runners')).not.toBeNull(); - expect(vm.$el.querySelector('.js-stuck-with-tags')).toBeNull(); - expect(vm.$el.querySelector('.js-stuck-no-active-runner')).toBeNull(); + expect(findStuckNoRunners().exists()).toBe(true); + expect(findStuckWithTags().exists()).toBe(false); + expect(findStuckNoActiveRunners().exists()).toBe(false); }); it('renders link to runners page', () => { - expect(vm.$el.querySelector('.js-runners-path').getAttribute('href')).toEqual( + expect(findRunnerPathLink().attributes('href')).toBe( '/root/project/runners#js-runners-settings', ); }); @@ -33,26 +52,27 @@ describe('Stuck Block Job component', () => { describe('with tags', () => { beforeEach(() => { - vm = mountComponent(Component, { + createWrapper({ hasNoRunnersForProject: false, - tags: ['docker', 'gitlab-org'], + tags, runnersPath: '/root/project/runners#js-runners-settings', }); }); it('renders information about the tags not being set', () => { - expect(vm.$el.querySelector('.js-stuck-no-runners')).toBeNull(); - expect(vm.$el.querySelector('.js-stuck-with-tags')).not.toBeNull(); - expect(vm.$el.querySelector('.js-stuck-no-active-runner')).toBeNull(); + expect(findStuckWithTags().exists()).toBe(true); + expect(findStuckNoActiveRunners().exists()).toBe(false); + expect(findStuckNoRunners().exists()).toBe(false); }); it('renders tags', () => { - expect(vm.$el.textContent).toContain('docker'); - expect(vm.$el.textContent).toContain('gitlab-org'); + findAllBadges().wrappers.forEach((badgeElt, index) => { + return expect(badgeElt.text()).toBe(tags[index]); + }); }); it('renders link to runners page', () => { - expect(vm.$el.querySelector('.js-runners-path').getAttribute('href')).toEqual( + expect(findRunnerPathLink().attributes('href')).toBe( '/root/project/runners#js-runners-settings', ); }); @@ -60,20 +80,20 @@ describe('Stuck Block Job component', () => { describe('without active runners', () => { beforeEach(() => { - vm = mountComponent(Component, { + createWrapper({ hasNoRunnersForProject: false, runnersPath: '/root/project/runners#js-runners-settings', }); }); it('renders information about project not having runners', () => { - expect(vm.$el.querySelector('.js-stuck-no-runners')).toBeNull(); - expect(vm.$el.querySelector('.js-stuck-with-tags')).toBeNull(); - expect(vm.$el.querySelector('.js-stuck-no-active-runner')).not.toBeNull(); + expect(findStuckNoActiveRunners().exists()).toBe(true); + expect(findStuckNoRunners().exists()).toBe(false); + expect(findStuckWithTags().exists()).toBe(false); }); it('renders link to runners page', () => { - expect(vm.$el.querySelector('.js-runners-path').getAttribute('href')).toEqual( + expect(findRunnerPathLink().attributes('href')).toBe( '/root/project/runners#js-runners-settings', ); }); |