Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 11:27:35 +0300
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /spec/frontend/jobs/components
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/frontend/jobs/components')
-rw-r--r--spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js76
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js132
-rw-r--r--spec/frontend/jobs/components/job_sidebar_retry_button_spec.js70
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js149
-rw-r--r--spec/frontend/jobs/components/sidebar_spec.js201
5 files changed, 511 insertions, 117 deletions
diff --git a/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js b/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js
new file mode 100644
index 00000000000..08973223c08
--- /dev/null
+++ b/spec/frontend/jobs/components/job_retry_forward_deployment_modal_spec.js
@@ -0,0 +1,76 @@
+import { GlLink, GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
+import { JOB_RETRY_FORWARD_DEPLOYMENT_MODAL } from '~/jobs/constants';
+import createStore from '~/jobs/store';
+import job from '../mock_data';
+
+describe('Job Retry Forward Deployment Modal', () => {
+ let store;
+ let wrapper;
+
+ const retryOutdatedJobDocsUrl = 'url-to-docs';
+ const findLink = () => wrapper.find(GlLink);
+ const findModal = () => wrapper.find(GlModal);
+
+ const createWrapper = ({ props = {}, provide = {}, stubs = {} } = {}) => {
+ store = createStore();
+ wrapper = shallowMount(JobRetryForwardDeploymentModal, {
+ propsData: {
+ modalId: 'modal-id',
+ href: job.retry_path,
+ ...props,
+ },
+ provide,
+ store,
+ stubs,
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(createWrapper);
+
+ describe('Modal configuration', () => {
+ it('should display the correct messages', () => {
+ const modal = findModal();
+ expect(modal.attributes('title')).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.title);
+ expect(modal.text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.info);
+ expect(modal.text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.areYouSure);
+ });
+ });
+
+ describe('Modal docs help link', () => {
+ it('should not display an info link when none is provided', () => {
+ createWrapper();
+
+ expect(findLink().exists()).toBe(false);
+ });
+
+ it('should display an info link when one is provided', () => {
+ createWrapper({ provide: { retryOutdatedJobDocsUrl } });
+
+ expect(findLink().attributes('href')).toBe(retryOutdatedJobDocsUrl);
+ expect(findLink().text()).toMatch(JOB_RETRY_FORWARD_DEPLOYMENT_MODAL.moreInfo);
+ });
+ });
+
+ describe('Modal actions', () => {
+ beforeEach(createWrapper);
+
+ it('should correctly configure the primary action', () => {
+ expect(findModal().props('actionPrimary').attributes).toMatchObject([
+ {
+ 'data-method': 'post',
+ href: job.retry_path,
+ variant: 'danger',
+ },
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
new file mode 100644
index 00000000000..be684769b46
--- /dev/null
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -0,0 +1,132 @@
+import { shallowMount } from '@vue/test-utils';
+import SidebarJobDetailsContainer from '~/jobs/components/sidebar_job_details_container.vue';
+import DetailRow from '~/jobs/components/sidebar_detail_row.vue';
+import createStore from '~/jobs/store';
+import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
+import job from '../mock_data';
+
+describe('Job Sidebar Details Container', () => {
+ let store;
+ let wrapper;
+
+ const findJobTimeout = () => wrapper.findByTestId('job-timeout');
+ const findJobTags = () => wrapper.findByTestId('job-tags');
+ const findAllDetailsRow = () => wrapper.findAll(DetailRow);
+
+ const createWrapper = ({ props = {} } = {}) => {
+ store = createStore();
+ wrapper = extendedWrapper(
+ shallowMount(SidebarJobDetailsContainer, {
+ propsData: props,
+ store,
+ stubs: {
+ DetailRow,
+ },
+ }),
+ );
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('when no details are available', () => {
+ it('should render an empty container', () => {
+ createWrapper();
+
+ expect(wrapper.isEmpty()).toBe(true);
+ });
+ });
+
+ describe('when some of the details are available', () => {
+ beforeEach(createWrapper);
+
+ it.each([
+ ['duration', 'Duration: 6 seconds'],
+ ['erased_at', 'Erased: 3 weeks ago'],
+ ['finished_at', 'Finished: 3 weeks ago'],
+ ['queued', 'Queued: 9 seconds'],
+ ['runner', 'Runner: local ci runner (#1)'],
+ ['coverage', 'Coverage: 20%'],
+ ])('uses %s to render job-%s', async (detail, value) => {
+ await store.dispatch('receiveJobSuccess', { [detail]: job[detail] });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(detailsRow).toHaveLength(1);
+ expect(detailsRow.at(0).text()).toBe(value);
+ });
+
+ it('only renders tags', async () => {
+ const { tags } = job;
+ await store.dispatch('receiveJobSuccess', { tags });
+ const tagsComponent = findJobTags();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(tagsComponent.text()).toBe('Tags: tag');
+ });
+ });
+
+ describe('when all the info are available', () => {
+ it('renders all the details components', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', job);
+
+ expect(findAllDetailsRow()).toHaveLength(7);
+ });
+ });
+
+ describe('timeout', () => {
+ const {
+ metadata: { timeout_human_readable, timeout_source },
+ } = job;
+
+ beforeEach(createWrapper);
+
+ it('does not render if metadata is empty', async () => {
+ const metadata = {};
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(true);
+ expect(detailsRow.exists()).toBe(false);
+ });
+
+ it('uses metadata to render timeout', async () => {
+ const metadata = { timeout_human_readable };
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(wrapper.isEmpty()).toBe(false);
+ expect(detailsRow).toHaveLength(1);
+ expect(detailsRow.at(0).text()).toBe('Timeout: 1m 40s');
+ });
+
+ it('uses metadata to render timeout and the source', async () => {
+ const metadata = { timeout_human_readable, timeout_source };
+ await store.dispatch('receiveJobSuccess', { metadata });
+ const detailsRow = findAllDetailsRow();
+
+ expect(detailsRow.at(0).text()).toBe('Timeout: 1m 40s (from runner)');
+ });
+
+ it('should not render when no time is provided', async () => {
+ const metadata = { timeout_source };
+ await store.dispatch('receiveJobSuccess', { metadata });
+
+ expect(findJobTimeout().exists()).toBe(false);
+ });
+
+ it('should pass the help URL', async () => {
+ const helpUrl = 'fakeUrl';
+ const props = { runnerHelpUrl: helpUrl };
+ createWrapper({ props });
+ await store.dispatch('receiveJobSuccess', { metadata: { timeout_human_readable } });
+
+ expect(findJobTimeout().props('helpUrl')).toBe(helpUrl);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
new file mode 100644
index 00000000000..4bf697ab7cc
--- /dev/null
+++ b/spec/frontend/jobs/components/job_sidebar_retry_button_spec.js
@@ -0,0 +1,70 @@
+import { GlButton, GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import job from '../mock_data';
+import JobsSidebarRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
+import createStore from '~/jobs/store';
+
+describe('Job Sidebar Retry Button', () => {
+ let store;
+ let wrapper;
+
+ const forwardDeploymentFailure = 'forward_deployment_failure';
+ const findRetryButton = () => wrapper.find(GlButton);
+ const findRetryLink = () => wrapper.find(GlLink);
+
+ const createWrapper = ({ props = {} } = {}) => {
+ store = createStore();
+ wrapper = shallowMount(JobsSidebarRetryButton, {
+ propsData: {
+ href: job.retry_path,
+ modalId: 'modal-id',
+ ...props,
+ },
+ store,
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(createWrapper);
+
+ it.each([
+ [null, false, true],
+ ['unmet_prerequisites', false, true],
+ [forwardDeploymentFailure, true, false],
+ ])(
+ 'when error is: %s, should render button: %s | should render link: %s',
+ async (failureReason, buttonExists, linkExists) => {
+ await store.dispatch('receiveJobSuccess', { ...job, failure_reason: failureReason });
+
+ expect(findRetryButton().exists()).toBe(buttonExists);
+ expect(findRetryLink().exists()).toBe(linkExists);
+ expect(wrapper.text()).toMatch('Retry');
+ },
+ );
+
+ describe('Button', () => {
+ it('should have the correct configuration', async () => {
+ await store.dispatch('receiveJobSuccess', { failure_reason: forwardDeploymentFailure });
+
+ expect(findRetryButton().attributes()).toMatchObject({
+ category: 'primary',
+ variant: 'info',
+ });
+ });
+ });
+
+ describe('Link', () => {
+ it('should have the correct configuration', () => {
+ expect(findRetryLink().attributes()).toMatchObject({
+ 'data-method': 'post',
+ href: job.retry_path,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
index c2412a807c3..314b23ec29b 100644
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ b/spec/frontend/jobs/components/log/line_spec.js
@@ -2,21 +2,26 @@ import { shallowMount } from '@vue/test-utils';
import Line from '~/jobs/components/log/line.vue';
import LineNumber from '~/jobs/components/log/line_number.vue';
+const httpUrl = 'http://example.com';
+const httpsUrl = 'https://example.com';
+
+const mockProps = ({ text = 'Running with gitlab-runner 12.1.0 (de7731dd)' } = {}) => ({
+ line: {
+ content: [
+ {
+ text,
+ style: 'term-fg-l-green',
+ },
+ ],
+ lineNumber: 0,
+ },
+ path: '/jashkenas/underscore/-/jobs/335',
+});
+
describe('Job Log Line', () => {
let wrapper;
-
- const data = {
- line: {
- content: [
- {
- text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
- style: 'term-fg-l-green',
- },
- ],
- lineNumber: 0,
- },
- path: '/jashkenas/underscore/-/jobs/335',
- };
+ let data;
+ let originalGon;
const createComponent = (props = {}) => {
wrapper = shallowMount(Line, {
@@ -26,12 +31,25 @@ describe('Job Log Line', () => {
});
};
+ const findLine = () => wrapper.find('span');
+ const findLink = () => findLine().find('a');
+ const findLinksAt = i =>
+ findLine()
+ .findAll('a')
+ .at(i);
+
beforeEach(() => {
+ originalGon = window.gon;
+ window.gon.features = {
+ ciJobLineLinks: false,
+ };
+
+ data = mockProps();
createComponent(data);
});
afterEach(() => {
- wrapper.destroy();
+ window.gon = originalGon;
});
it('renders the line number component', () => {
@@ -39,10 +57,109 @@ describe('Job Log Line', () => {
});
it('renders a span the provided text', () => {
- expect(wrapper.find('span').text()).toBe(data.line.content[0].text);
+ expect(findLine().text()).toBe(data.line.content[0].text);
});
it('renders the provided style as a class attribute', () => {
- expect(wrapper.find('span').classes()).toContain(data.line.content[0].style);
+ expect(findLine().classes()).toContain(data.line.content[0].style);
+ });
+
+ describe.each([true, false])('when feature ci_job_line_links enabled = %p', ciJobLineLinks => {
+ beforeEach(() => {
+ window.gon.features = {
+ ciJobLineLinks,
+ };
+ });
+
+ it('renders text with symbols', () => {
+ const text = 'apt-get update < /dev/null > /dev/null';
+ createComponent(mockProps({ text }));
+
+ expect(findLine().text()).toBe(text);
+ });
+
+ it.each`
+ tag | text
+ ${'a'} | ${'<a href="#">linked</a>'}
+ ${'script'} | ${'<script>doEvil();</script>'}
+ ${'strong'} | ${'<strong>highlighted</strong>'}
+ `('escapes `<$tag>` tags in text', ({ tag, text }) => {
+ createComponent(mockProps({ text }));
+
+ expect(
+ findLine()
+ .find(tag)
+ .exists(),
+ ).toBe(false);
+ expect(findLine().text()).toBe(text);
+ });
+ });
+
+ describe('when ci_job_line_links is enabled', () => {
+ beforeEach(() => {
+ window.gon.features = {
+ ciJobLineLinks: true,
+ };
+ });
+
+ it('renders an http link', () => {
+ createComponent(mockProps({ text: httpUrl }));
+
+ expect(findLink().text()).toBe(httpUrl);
+ expect(findLink().attributes().href).toBe(httpUrl);
+ });
+
+ it('renders an https link', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().text()).toBe(httpsUrl);
+ expect(findLink().attributes().href).toBe(httpsUrl);
+ });
+
+ it('renders a multiple links surrounded by text', () => {
+ createComponent(mockProps({ text: `My HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl}` }));
+ expect(findLine().text()).toBe(
+ 'My HTTP url: http://example.com and my HTTPS url: https://example.com',
+ );
+ expect(findLinksAt(0).attributes().href).toBe(httpUrl);
+ expect(findLinksAt(1).attributes().href).toBe(httpsUrl);
+ });
+
+ it('renders a link with rel nofollow and noopener', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().attributes().rel).toBe('nofollow noopener noreferrer');
+ });
+
+ it('renders a link with corresponding styles', () => {
+ createComponent(mockProps({ text: httpsUrl }));
+
+ expect(findLink().classes()).toEqual(['gl-reset-color!', 'gl-text-decoration-underline']);
+ });
+
+ it('render links surrounded by text', () => {
+ createComponent(
+ mockProps({ text: `My HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl} are here.` }),
+ );
+ expect(findLine().text()).toBe(
+ 'My HTTP url: http://example.com and my HTTPS url: https://example.com are here.',
+ );
+ expect(findLinksAt(0).attributes().href).toBe(httpUrl);
+ expect(findLinksAt(1).attributes().href).toBe(httpsUrl);
+ });
+
+ const jshref = 'javascript:doEvil();'; // eslint-disable-line no-script-url
+
+ test.each`
+ type | text
+ ${'js'} | ${jshref}
+ ${'file'} | ${'file:///a-file'}
+ ${'ftp'} | ${'ftp://example.com/file'}
+ ${'email'} | ${'email@example.com'}
+ ${'no scheme'} | ${'example.com/page'}
+ `('does not render a $type link', ({ text }) => {
+ createComponent(mockProps({ text }));
+ expect(findLink().exists()).toBe(false);
+ });
});
});
diff --git a/spec/frontend/jobs/components/sidebar_spec.js b/spec/frontend/jobs/components/sidebar_spec.js
index 48788df0c93..1d4be2fb81e 100644
--- a/spec/frontend/jobs/components/sidebar_spec.js
+++ b/spec/frontend/jobs/components/sidebar_spec.js
@@ -1,167 +1,166 @@
-import Vue from 'vue';
-import sidebarDetailsBlock from '~/jobs/components/sidebar.vue';
+import { shallowMount } from '@vue/test-utils';
+import Sidebar, { forwardDeploymentFailureModalId } from '~/jobs/components/sidebar.vue';
+import StagesDropdown from '~/jobs/components/stages_dropdown.vue';
+import JobsContainer from '~/jobs/components/jobs_container.vue';
+import JobRetryForwardDeploymentModal from '~/jobs/components/job_retry_forward_deployment_modal.vue';
+import JobRetryButton from '~/jobs/components/job_sidebar_retry_button.vue';
import createStore from '~/jobs/store';
import job, { jobsInStage } from '../mock_data';
-import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
-import { trimText } from '../../helpers/text_helper';
+import { extendedWrapper } from '../../helpers/vue_test_utils_helper';
describe('Sidebar details block', () => {
- const SidebarComponent = Vue.extend(sidebarDetailsBlock);
- let vm;
let store;
+ let wrapper;
- beforeEach(() => {
+ const forwardDeploymentFailure = 'forward_deployment_failure';
+ const findModal = () => wrapper.find(JobRetryForwardDeploymentModal);
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findNewIssueButton = () => wrapper.findByTestId('job-new-issue');
+ const findRetryButton = () => wrapper.find(JobRetryButton);
+ const findTerminalLink = () => wrapper.findByTestId('terminal-link');
+
+ const createWrapper = ({ props = {} } = {}) => {
store = createStore();
- });
+ wrapper = extendedWrapper(
+ shallowMount(Sidebar, {
+ ...props,
+ store,
+ }),
+ );
+ };
afterEach(() => {
- vm.$destroy();
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
});
describe('when there is no retry path retry', () => {
- it('should not render a retry button', () => {
- const copy = { ...job };
- delete copy.retry_path;
-
- store.dispatch('receiveJobSuccess', copy);
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
+ it('should not render a retry button', async () => {
+ createWrapper();
+ const copy = { ...job, retry_path: null };
+ await store.dispatch('receiveJobSuccess', copy);
- expect(vm.$el.querySelector('.js-retry-button')).toBeNull();
+ expect(findRetryButton().exists()).toBe(false);
});
});
describe('without terminal path', () => {
- it('does not render terminal link', () => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
+ it('does not render terminal link', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', job);
- expect(vm.$el.querySelector('.js-terminal-link')).toBeNull();
+ expect(findTerminalLink().exists()).toBe(false);
});
});
describe('with terminal path', () => {
- it('renders terminal link', () => {
- store.dispatch('receiveJobSuccess', { ...job, terminal_path: 'job/43123/terminal' });
- vm = mountComponentWithStore(SidebarComponent, {
- store,
- });
+ it('renders terminal link', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', { ...job, terminal_path: 'job/43123/terminal' });
- expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
+ expect(findTerminalLink().exists()).toBe(true);
});
});
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
describe('actions', () => {
- it('should render link to new issue', () => {
- expect(vm.$el.querySelector('[data-testid="job-new-issue"]').getAttribute('href')).toEqual(
- job.new_issue_path,
- );
+ beforeEach(() => {
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', job);
+ });
- expect(vm.$el.querySelector('[data-testid="job-new-issue"]').textContent.trim()).toEqual(
- 'New issue',
- );
+ it('should render link to new issue', () => {
+ expect(findNewIssueButton().attributes('href')).toBe(job.new_issue_path);
+ expect(findNewIssueButton().text()).toBe('New issue');
});
- it('should render link to retry job', () => {
- expect(vm.$el.querySelector('.js-retry-button').getAttribute('href')).toEqual(job.retry_path);
+ it('should render the retry button', () => {
+ expect(findRetryButton().props('href')).toBe(job.retry_path);
});
it('should render link to cancel job', () => {
- expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
+ expect(findCancelButton().text()).toMatch('Cancel');
+ expect(findCancelButton().attributes('href')).toBe(job.cancel_path);
});
});
- describe('information', () => {
- it('should render job duration', () => {
- expect(trimText(vm.$el.querySelector('.js-job-duration').textContent)).toEqual(
- 'Duration: 6 seconds',
- );
- });
-
- it('should render erased date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-erased').textContent)).toEqual(
- 'Erased: 3 weeks ago',
- );
- });
-
- it('should render finished date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-finished').textContent)).toEqual(
- 'Finished: 3 weeks ago',
- );
- });
-
- it('should render queued date', () => {
- expect(trimText(vm.$el.querySelector('.js-job-queued').textContent)).toEqual(
- 'Queued: 9 seconds',
+ describe('forward deployment failure', () => {
+ describe('when the relevant data is missing', () => {
+ it.each`
+ retryPath | failureReason
+ ${null} | ${null}
+ ${''} | ${''}
+ ${job.retry_path} | ${''}
+ ${''} | ${forwardDeploymentFailure}
+ ${job.retry_path} | ${'unmet_prerequisites'}
+ `(
+ 'should not render the modal when path and failure are $retryPath, $failureReason',
+ async ({ retryPath, failureReason }) => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', {
+ ...job,
+ failure_reason: failureReason,
+ retry_path: retryPath,
+ });
+ expect(findModal().exists()).toBe(false);
+ },
);
});
- it('should render runner ID', () => {
- expect(trimText(vm.$el.querySelector('.js-job-runner').textContent)).toEqual(
- 'Runner: local ci runner (#1)',
- );
- });
+ describe('when there is the relevant error', () => {
+ beforeEach(() => {
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', {
+ ...job,
+ failure_reason: forwardDeploymentFailure,
+ });
+ });
- it('should render timeout information', () => {
- expect(trimText(vm.$el.querySelector('.js-job-timeout').textContent)).toEqual(
- 'Timeout: 1m 40s (from runner)',
- );
- });
+ it('should render the modal', () => {
+ expect(findModal().exists()).toBe(true);
+ });
- it('should render coverage', () => {
- expect(trimText(vm.$el.querySelector('.js-job-coverage').textContent)).toEqual(
- 'Coverage: 20%',
- );
- });
+ it('should provide the modal id to the button and modal', () => {
+ expect(findRetryButton().props('modalId')).toBe(forwardDeploymentFailureModalId);
+ expect(findModal().props('modalId')).toBe(forwardDeploymentFailureModalId);
+ });
- it('should render tags', () => {
- expect(trimText(vm.$el.querySelector('.js-job-tags').textContent)).toEqual('Tags: tag');
+ it('should provide the retry path to the button and modal', () => {
+ expect(findRetryButton().props('href')).toBe(job.retry_path);
+ expect(findModal().props('href')).toBe(job.retry_path);
+ });
});
});
describe('stages dropdown', () => {
beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
+ createWrapper();
+ return store.dispatch('receiveJobSuccess', { ...job, stage: 'aStage' });
});
describe('with stages', () => {
- beforeEach(() => {
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
-
it('renders value provided as selectedStage as selected', () => {
- expect(vm.$el.querySelector('.js-selected-stage').textContent.trim()).toEqual(
- vm.selectedStage,
- );
+ expect(wrapper.find(StagesDropdown).props('selectedStage')).toBe('aStage');
});
});
describe('without jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- vm = mountComponentWithStore(SidebarComponent, { store });
- });
+ beforeEach(() => store.dispatch('receiveJobSuccess', job));
- it('does not render job container', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).toBeNull();
+ it('does not render jobs container', () => {
+ expect(wrapper.find(JobsContainer).exists()).toBe(false);
});
});
describe('with jobs for stages', () => {
- beforeEach(() => {
- store.dispatch('receiveJobSuccess', job);
- store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
- vm = mountComponentWithStore(SidebarComponent, { store });
+ beforeEach(async () => {
+ await store.dispatch('receiveJobSuccess', job);
+ await store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
});
it('renders list of jobs', () => {
- expect(vm.$el.querySelector('.js-jobs-container')).not.toBeNull();
+ expect(wrapper.find(JobsContainer).exists()).toBe(true);
});
});
});