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:
Diffstat (limited to 'spec/frontend/jobs')
-rw-r--r--spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js71
-rw-r--r--spec/frontend/jobs/components/filtered_search/tokens/job_status_token_spec.js58
-rw-r--r--spec/frontend/jobs/components/filtered_search/utils_spec.js19
-rw-r--r--spec/frontend/jobs/components/job/artifacts_block_spec.js193
-rw-r--r--spec/frontend/jobs/components/job/commit_block_spec.js66
-rw-r--r--spec/frontend/jobs/components/job/empty_state_spec.js140
-rw-r--r--spec/frontend/jobs/components/job/environments_block_spec.js260
-rw-r--r--spec/frontend/jobs/components/job/erased_block_spec.js59
-rw-r--r--spec/frontend/jobs/components/job/job_app_spec.js343
-rw-r--r--spec/frontend/jobs/components/job/job_container_item_spec.js87
-rw-r--r--spec/frontend/jobs/components/job/job_log_controllers_spec.js323
-rw-r--r--spec/frontend/jobs/components/job/job_retry_forward_deployment_modal_spec.js67
-rw-r--r--spec/frontend/jobs/components/job/job_sidebar_details_container_spec.js133
-rw-r--r--spec/frontend/jobs/components/job/job_sidebar_retry_button_spec.js64
-rw-r--r--spec/frontend/jobs/components/job/jobs_container_spec.js143
-rw-r--r--spec/frontend/jobs/components/job/manual_variables_form_spec.js364
-rw-r--r--spec/frontend/jobs/components/job/mock_data.js123
-rw-r--r--spec/frontend/jobs/components/job/sidebar_detail_row_spec.js68
-rw-r--r--spec/frontend/jobs/components/job/sidebar_header_spec.js87
-rw-r--r--spec/frontend/jobs/components/job/sidebar_spec.js216
-rw-r--r--spec/frontend/jobs/components/job/stages_dropdown_spec.js191
-rw-r--r--spec/frontend/jobs/components/job/stuck_block_spec.js94
-rw-r--r--spec/frontend/jobs/components/job/trigger_block_spec.js81
-rw-r--r--spec/frontend/jobs/components/job/unmet_prerequisites_block_spec.js37
-rw-r--r--spec/frontend/jobs/components/log/collapsible_section_spec.js71
-rw-r--r--spec/frontend/jobs/components/log/duration_badge_spec.js26
-rw-r--r--spec/frontend/jobs/components/log/line_header_spec.js119
-rw-r--r--spec/frontend/jobs/components/log/line_number_spec.js35
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js267
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js135
-rw-r--r--spec/frontend/jobs/components/log/mock_data.js218
-rw-r--r--spec/frontend/jobs/components/table/cells/actions_cell_spec.js240
-rw-r--r--spec/frontend/jobs/components/table/cells/duration_cell_spec.js77
-rw-r--r--spec/frontend/jobs/components/table/cells/job_cell_spec.js142
-rw-r--r--spec/frontend/jobs/components/table/cells/pipeline_cell_spec.js78
-rw-r--r--spec/frontend/jobs/components/table/graphql/cache_config_spec.js106
-rw-r--r--spec/frontend/jobs/components/table/job_table_app_spec.js338
-rw-r--r--spec/frontend/jobs/components/table/jobs_table_empty_state_spec.js37
-rw-r--r--spec/frontend/jobs/components/table/jobs_table_spec.js98
-rw-r--r--spec/frontend/jobs/components/table/jobs_table_tabs_spec.js81
-rw-r--r--spec/frontend/jobs/mixins/delayed_job_mixin_spec.js119
-rw-r--r--spec/frontend/jobs/mock_data.js1628
-rw-r--r--spec/frontend/jobs/store/actions_spec.js502
-rw-r--r--spec/frontend/jobs/store/getters_spec.js245
-rw-r--r--spec/frontend/jobs/store/helpers.js5
-rw-r--r--spec/frontend/jobs/store/mutations_spec.js269
-rw-r--r--spec/frontend/jobs/store/utils_spec.js510
47 files changed, 0 insertions, 8633 deletions
diff --git a/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js b/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js
deleted file mode 100644
index 5ecddc7efd6..00000000000
--- a/spec/frontend/jobs/components/filtered_search/jobs_filtered_search_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { GlFilteredSearch } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import {
- OPERATORS_IS,
- TOKEN_TITLE_STATUS,
- TOKEN_TYPE_STATUS,
-} from '~/vue_shared/components/filtered_search_bar/constants';
-import JobsFilteredSearch from '~/jobs/components/filtered_search/jobs_filtered_search.vue';
-import { mockFailedSearchToken } from '../../mock_data';
-
-describe('Jobs filtered search', () => {
- let wrapper;
-
- const findFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
- const getSearchToken = (type) =>
- findFilteredSearch()
- .props('availableTokens')
- .find((token) => token.type === type);
-
- const findStatusToken = () => getSearchToken('status');
-
- const createComponent = (props) => {
- wrapper = shallowMount(JobsFilteredSearch, {
- propsData: {
- ...props,
- },
- });
- };
-
- it('displays filtered search', () => {
- createComponent();
-
- expect(findFilteredSearch().exists()).toBe(true);
- });
-
- it('displays status token', () => {
- createComponent();
-
- expect(findStatusToken()).toMatchObject({
- type: TOKEN_TYPE_STATUS,
- icon: 'status',
- title: TOKEN_TITLE_STATUS,
- unique: true,
- operators: OPERATORS_IS,
- });
- });
-
- it('emits filter token to parent component', () => {
- createComponent();
-
- findFilteredSearch().vm.$emit('submit', mockFailedSearchToken);
-
- expect(wrapper.emitted('filterJobsBySearch')).toEqual([[mockFailedSearchToken]]);
- });
-
- it('filtered search value is empty array when no query string is passed', () => {
- createComponent();
-
- expect(findFilteredSearch().props('value')).toEqual([]);
- });
-
- it('filtered search returns correct data shape when passed query string', () => {
- const value = 'SUCCESS';
-
- createComponent({ queryString: { statuses: value } });
-
- expect(findFilteredSearch().props('value')).toEqual([
- { type: TOKEN_TYPE_STATUS, value: { data: value, operator: '=' } },
- ]);
- });
-});
diff --git a/spec/frontend/jobs/components/filtered_search/tokens/job_status_token_spec.js b/spec/frontend/jobs/components/filtered_search/tokens/job_status_token_spec.js
deleted file mode 100644
index 6755b854f01..00000000000
--- a/spec/frontend/jobs/components/filtered_search/tokens/job_status_token_spec.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import { GlFilteredSearchToken, GlFilteredSearchSuggestion, GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { stubComponent } from 'helpers/stub_component';
-import JobStatusToken from '~/jobs/components/filtered_search/tokens/job_status_token.vue';
-import {
- TOKEN_TITLE_STATUS,
- TOKEN_TYPE_STATUS,
-} from '~/vue_shared/components/filtered_search_bar/constants';
-
-describe('Job Status Token', () => {
- let wrapper;
-
- const findFilteredSearchToken = () => wrapper.findComponent(GlFilteredSearchToken);
- const findAllFilteredSearchSuggestions = () =>
- wrapper.findAllComponents(GlFilteredSearchSuggestion);
- const findAllGlIcons = () => wrapper.findAllComponents(GlIcon);
-
- const defaultProps = {
- config: {
- type: TOKEN_TYPE_STATUS,
- icon: 'status',
- title: TOKEN_TITLE_STATUS,
- unique: true,
- },
- value: {
- data: '',
- },
- cursorPosition: 'start',
- };
-
- const createComponent = () => {
- wrapper = shallowMount(JobStatusToken, {
- propsData: {
- ...defaultProps,
- },
- stubs: {
- GlFilteredSearchToken: stubComponent(GlFilteredSearchToken, {
- template: `<div><slot name="suggestions"></slot></div>`,
- }),
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- it('passes config correctly', () => {
- expect(findFilteredSearchToken().props('config')).toEqual(defaultProps.config);
- });
-
- it('renders all job statuses available', () => {
- const expectedLength = 11;
-
- expect(findAllFilteredSearchSuggestions()).toHaveLength(expectedLength);
- expect(findAllGlIcons()).toHaveLength(expectedLength);
- });
-});
diff --git a/spec/frontend/jobs/components/filtered_search/utils_spec.js b/spec/frontend/jobs/components/filtered_search/utils_spec.js
deleted file mode 100644
index 8440ab42b86..00000000000
--- a/spec/frontend/jobs/components/filtered_search/utils_spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import { validateQueryString } from '~/jobs/components/filtered_search/utils';
-
-describe('Filtered search utils', () => {
- describe('validateQueryString', () => {
- it.each`
- queryStringObject | expected
- ${{ statuses: 'SUCCESS' }} | ${{ statuses: 'SUCCESS' }}
- ${{ statuses: 'failed' }} | ${{ statuses: 'FAILED' }}
- ${{ wrong: 'SUCCESS' }} | ${null}
- ${{ statuses: 'wrong' }} | ${null}
- ${{ wrong: 'wrong' }} | ${null}
- `(
- 'when provided $queryStringObject, the expected result is $expected',
- ({ queryStringObject, expected }) => {
- expect(validateQueryString(queryStringObject)).toEqual(expected);
- },
- );
- });
-});
diff --git a/spec/frontend/jobs/components/job/artifacts_block_spec.js b/spec/frontend/jobs/components/job/artifacts_block_spec.js
deleted file mode 100644
index f9e52a5ae43..00000000000
--- a/spec/frontend/jobs/components/job/artifacts_block_spec.js
+++ /dev/null
@@ -1,193 +0,0 @@
-import { GlPopover } from '@gitlab/ui';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import { trimText } from 'helpers/text_helper';
-import ArtifactsBlock from '~/jobs/components/job/sidebar/artifacts_block.vue';
-import { getTimeago } from '~/lib/utils/datetime_utility';
-
-describe('Artifacts block', () => {
- let wrapper;
-
- const createWrapper = (propsData) =>
- mountExtended(ArtifactsBlock, {
- propsData: {
- helpUrl: 'help-url',
- ...propsData,
- },
- });
-
- const findArtifactRemoveElt = () => wrapper.findByTestId('artifacts-remove-timeline');
- const findJobLockedElt = () => wrapper.findByTestId('job-locked-message');
- const findKeepBtn = () => wrapper.findByTestId('keep-artifacts');
- const findDownloadBtn = () => wrapper.findByTestId('download-artifacts');
- const findBrowseBtn = () => wrapper.findByTestId('browse-artifacts');
- const findArtifactsHelpLink = () => wrapper.findByTestId('artifacts-help-link');
- const findPopover = () => wrapper.findComponent(GlPopover);
-
- const expireAt = '2018-08-14T09:38:49.157Z';
- const timeago = getTimeago();
- const formattedDate = timeago.format(expireAt);
- const lockedText =
- 'These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available.';
-
- const expiredArtifact = {
- expire_at: expireAt,
- expired: true,
- locked: false,
- };
-
- const nonExpiredArtifact = {
- download_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/download',
- browse_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/browse',
- keep_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/keep',
- expire_at: expireAt,
- expired: false,
- locked: false,
- };
-
- const lockedExpiredArtifact = {
- ...expiredArtifact,
- download_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/download',
- browse_path: '/gitlab-org/gitlab-foss/-/jobs/98314558/artifacts/browse',
- expired: true,
- locked: true,
- };
-
- const lockedNonExpiredArtifact = {
- ...nonExpiredArtifact,
- keep_path: undefined,
- locked: true,
- };
-
- describe('with expired artifacts that are not locked', () => {
- beforeEach(() => {
- wrapper = createWrapper({
- artifact: expiredArtifact,
- });
- });
-
- it('renders expired artifact date and info', () => {
- expect(trimText(findArtifactRemoveElt().text())).toBe(
- `The artifacts were removed ${formattedDate}`,
- );
-
- expect(
- findArtifactRemoveElt()
- .find('[data-testid="artifact-expired-help-link"]')
- .attributes('href'),
- ).toBe('help-url');
- });
-
- it('does not show the keep button', () => {
- expect(findKeepBtn().exists()).toBe(false);
- });
-
- it('does not show the download button', () => {
- expect(findDownloadBtn().exists()).toBe(false);
- });
-
- it('does not show the browse button', () => {
- expect(findBrowseBtn().exists()).toBe(false);
- });
- });
-
- describe('with artifacts that will expire', () => {
- beforeEach(() => {
- wrapper = createWrapper({
- artifact: nonExpiredArtifact,
- });
- });
-
- it('renders will expire artifact date and info', () => {
- expect(trimText(findArtifactRemoveElt().text())).toBe(
- `The artifacts will be removed ${formattedDate}`,
- );
-
- expect(
- findArtifactRemoveElt()
- .find('[data-testid="artifact-expired-help-link"]')
- .attributes('href'),
- ).toBe('help-url');
- });
-
- it('renders the keep button', () => {
- expect(findKeepBtn().exists()).toBe(true);
- });
-
- it('renders the download button', () => {
- expect(findDownloadBtn().exists()).toBe(true);
- });
-
- it('renders the browse button', () => {
- expect(findBrowseBtn().exists()).toBe(true);
- });
- });
-
- describe('with expired locked artifacts', () => {
- beforeEach(() => {
- wrapper = createWrapper({
- artifact: lockedExpiredArtifact,
- });
- });
-
- it('renders the information that the artefacts are locked', () => {
- expect(findArtifactRemoveElt().exists()).toBe(false);
- expect(trimText(findJobLockedElt().text())).toBe(lockedText);
- });
-
- it('does not render the keep button', () => {
- expect(findKeepBtn().exists()).toBe(false);
- });
-
- it('renders the download button', () => {
- expect(findDownloadBtn().exists()).toBe(true);
- });
-
- it('renders the browse button', () => {
- expect(findBrowseBtn().exists()).toBe(true);
- });
- });
-
- describe('with non expired locked artifacts', () => {
- beforeEach(() => {
- wrapper = createWrapper({
- artifact: lockedNonExpiredArtifact,
- });
- });
-
- it('renders the information that the artefacts are locked', () => {
- expect(findArtifactRemoveElt().exists()).toBe(false);
- expect(trimText(findJobLockedElt().text())).toBe(lockedText);
- });
-
- it('does not render the keep button', () => {
- expect(findKeepBtn().exists()).toBe(false);
- });
-
- it('renders the download button', () => {
- expect(findDownloadBtn().exists()).toBe(true);
- });
-
- it('renders the browse button', () => {
- expect(findBrowseBtn().exists()).toBe(true);
- });
- });
-
- describe('artifacts help text', () => {
- beforeEach(() => {
- wrapper = createWrapper({
- artifact: lockedNonExpiredArtifact,
- });
- });
-
- it('displays help text', () => {
- const expectedHelpText =
- 'Job artifacts are files that are configured to be uploaded when a job finishes execution. Artifacts could be compiled files, unit tests or scanning reports, or any other files generated by a job.';
-
- expect(findPopover().text()).toBe(expectedHelpText);
- });
-
- it('links to artifacts help page', () => {
- expect(findArtifactsHelpLink().attributes('href')).toBe('/help/ci/jobs/job_artifacts');
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/commit_block_spec.js b/spec/frontend/jobs/components/job/commit_block_spec.js
deleted file mode 100644
index 1c28b5079d7..00000000000
--- a/spec/frontend/jobs/components/job/commit_block_spec.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import CommitBlock from '~/jobs/components/job/sidebar/commit_block.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-
-describe('Commit block', () => {
- let wrapper;
-
- const commit = {
- short_id: '1f0fb84f',
- id: '1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- commit_path: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- title: 'Update README.md',
- };
-
- const mergeRequest = {
- iid: '!21244',
- path: 'merge_requests/21244',
- };
-
- const findCommitSha = () => wrapper.findByTestId('commit-sha');
- const findLinkSha = () => wrapper.findByTestId('link-commit');
-
- const mountComponent = (props) => {
- wrapper = extendedWrapper(
- shallowMount(CommitBlock, {
- propsData: {
- commit,
- ...props,
- },
- }),
- );
- };
-
- describe('without merge request', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders pipeline short sha link', () => {
- expect(findCommitSha().attributes('href')).toBe(commit.commit_path);
- expect(findCommitSha().text()).toBe(commit.short_id);
- });
-
- it('renders clipboard button', () => {
- expect(wrapper.findComponent(ClipboardButton).attributes('text')).toBe(commit.id);
- });
-
- it('renders git commit title', () => {
- expect(wrapper.text()).toContain(commit.title);
- });
-
- it('does not render merge request', () => {
- expect(findLinkSha().exists()).toBe(false);
- });
- });
-
- describe('with merge request', () => {
- it('renders merge request link and reference', () => {
- mountComponent({ mergeRequest });
-
- expect(findLinkSha().attributes('href')).toBe(mergeRequest.path);
- expect(findLinkSha().text()).toBe(`!${mergeRequest.iid}`);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/empty_state_spec.js b/spec/frontend/jobs/components/job/empty_state_spec.js
deleted file mode 100644
index 970c2591795..00000000000
--- a/spec/frontend/jobs/components/job/empty_state_spec.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import EmptyState from '~/jobs/components/job/empty_state.vue';
-import ManualVariablesForm from '~/jobs/components/job/manual_variables_form.vue';
-import { mockFullPath, mockId } from './mock_data';
-
-describe('Empty State', () => {
- let wrapper;
-
- const defaultProps = {
- illustrationPath: 'illustrations/pending_job_empty.svg',
- illustrationSizeClass: 'svg-430',
- jobId: mockId,
- title: 'This job has not started yet',
- playable: false,
- isRetryable: true,
- };
-
- const createWrapper = (props) => {
- wrapper = shallowMountExtended(EmptyState, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- provide: {
- projectPath: mockFullPath,
- },
- });
- };
-
- 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.findByTestId('job-empty-state-title');
- const findContent = () => wrapper.findByTestId('job-empty-state-content');
- const findAction = () => wrapper.findByTestId('job-empty-state-action');
- const findManualVarsForm = () => wrapper.findComponent(ManualVariablesForm);
-
- describe('renders image and title', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('renders empty state image', () => {
- expect(findEmptyStateImage().exists()).toBe(true);
- });
-
- it('renders provided title', () => {
- expect(findTitle().text().trim()).toBe(defaultProps.title);
- });
- });
-
- describe('with content', () => {
- beforeEach(() => {
- createWrapper({ content });
- });
-
- it('renders content', () => {
- expect(findContent().text().trim()).toBe(content);
- });
- });
-
- describe('without content', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('does not render content', () => {
- expect(findContent().exists()).toBe(false);
- });
- });
-
- describe('with action', () => {
- beforeEach(() => {
- createWrapper({
- action: {
- path: 'runner',
- button_title: 'Check runner',
- method: 'post',
- },
- });
- });
-
- it('renders action', () => {
- expect(findAction().attributes('href')).toBe('runner');
- });
- });
-
- describe('without action', () => {
- beforeEach(() => {
- createWrapper({
- action: null,
- });
- });
-
- it('does not render action', () => {
- expect(findAction().exists()).toBe(false);
- });
-
- it('does not render manual variables form', () => {
- expect(findManualVarsForm().exists()).toBe(false);
- });
- });
-
- describe('with playable action and not scheduled job', () => {
- beforeEach(() => {
- createWrapper({
- content,
- playable: true,
- scheduled: false,
- action: {
- path: 'runner',
- button_title: 'Check runner',
- method: 'post',
- },
- });
- });
-
- it('renders manual variables form', () => {
- expect(findManualVarsForm().exists()).toBe(true);
- });
-
- it('does not render the empty state action', () => {
- expect(findAction().exists()).toBe(false);
- });
- });
-
- describe('with playable action and scheduled job', () => {
- beforeEach(() => {
- createWrapper({
- playable: true,
- scheduled: true,
- content,
- });
- });
-
- it('does not render manual variables form', () => {
- expect(findManualVarsForm().exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/environments_block_spec.js b/spec/frontend/jobs/components/job/environments_block_spec.js
deleted file mode 100644
index ab36f79ea5e..00000000000
--- a/spec/frontend/jobs/components/job/environments_block_spec.js
+++ /dev/null
@@ -1,260 +0,0 @@
-import { mount } from '@vue/test-utils';
-import EnvironmentsBlock from '~/jobs/components/job/environments_block.vue';
-
-const TEST_CLUSTER_NAME = 'test_cluster';
-const TEST_CLUSTER_PATH = 'path/to/test_cluster';
-const TEST_KUBERNETES_NAMESPACE = 'this-is-a-kubernetes-namespace';
-
-describe('Environments block', () => {
- let wrapper;
-
- const status = {
- group: 'success',
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- };
-
- const environment = {
- environment_path: '/environment',
- name: 'environment',
- };
-
- const lastDeployment = { iid: 'deployment', deployable: { build_path: 'bar' } };
-
- const createEnvironmentWithLastDeployment = () => ({
- ...environment,
- last_deployment: { ...lastDeployment },
- });
-
- const createDeploymentWithCluster = () => ({ name: TEST_CLUSTER_NAME, path: TEST_CLUSTER_PATH });
-
- const createDeploymentWithClusterAndKubernetesNamespace = () => ({
- name: TEST_CLUSTER_NAME,
- path: TEST_CLUSTER_PATH,
- kubernetes_namespace: TEST_KUBERNETES_NAMESPACE,
- });
-
- const createComponent = (deploymentStatus = {}, deploymentCluster = {}) => {
- wrapper = mount(EnvironmentsBlock, {
- propsData: {
- deploymentStatus,
- deploymentCluster,
- iconStatus: status,
- },
- });
- };
-
- const findText = () => wrapper.findComponent(EnvironmentsBlock).text();
- const findJobDeploymentLink = () => wrapper.find('[data-testid="job-deployment-link"]');
- const findEnvironmentLink = () => wrapper.find('[data-testid="job-environment-link"]');
- const findClusterLink = () => wrapper.find('[data-testid="job-cluster-link"]');
-
- describe('with last deployment', () => {
- it('renders info for most recent deployment', () => {
- createComponent({
- status: 'last',
- environment,
- });
-
- expect(findText()).toBe('This job is deployed to environment.');
- });
-
- describe('when there is a cluster', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toBe(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
- });
-
- describe('when there is a kubernetes namespace', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithClusterAndKubernetesNamespace(),
- );
-
- expect(findText()).toBe(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}.`,
- );
- });
- });
- });
- });
-
- describe('with out of date deployment', () => {
- describe('with last deployment', () => {
- it('renders info for out date and most recent', () => {
- createComponent({
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- });
-
- expect(findText()).toBe(
- 'This job is an out-of-date deployment to environment. View the most recent deployment.',
- );
-
- expect(findJobDeploymentLink().attributes('href')).toBe('bar');
- });
-
- describe('when there is a cluster', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toBe(
- `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`,
- );
- });
-
- describe('when there is a kubernetes namespace', () => {
- it('renders info with cluster', () => {
- createComponent(
- {
- status: 'out_of_date',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithClusterAndKubernetesNamespace(),
- );
-
- expect(findText()).toBe(
- `This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}. View the most recent deployment.`,
- );
- });
- });
- });
- });
-
- describe('without last deployment', () => {
- it('renders info about out of date deployment', () => {
- createComponent({
- status: 'out_of_date',
- environment,
- });
-
- expect(findText()).toBe('This job is an out-of-date deployment to environment.');
- });
- });
- });
-
- describe('with failed deployment', () => {
- it('renders info about failed deployment', () => {
- createComponent({
- status: 'failed',
- environment,
- });
-
- expect(findText()).toBe('The deployment of this job to environment did not succeed.');
- });
- });
-
- describe('creating deployment', () => {
- describe('with last deployment', () => {
- it('renders info about creating deployment and overriding latest deployment', () => {
- createComponent({
- status: 'creating',
- environment: createEnvironmentWithLastDeployment(),
- });
-
- expect(findText()).toBe(
- 'This job is creating a deployment to environment. This will overwrite the latest deployment.',
- );
-
- expect(findEnvironmentLink().attributes('href')).toBe(environment.environment_path);
-
- expect(findJobDeploymentLink().attributes('href')).toBe('bar');
-
- expect(findClusterLink().exists()).toBe(false);
- });
- });
-
- describe('without last deployment', () => {
- it('renders info about deployment being created', () => {
- createComponent({
- status: 'creating',
- environment,
- });
-
- expect(findText()).toBe('This job is creating a deployment to environment.');
- });
-
- describe('when there is a cluster', () => {
- it('inclues information about the cluster', () => {
- createComponent(
- {
- status: 'creating',
- environment,
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toBe(
- `This job is creating a deployment to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
- });
- });
- });
-
- describe('without environment', () => {
- it('does not render environment link', () => {
- createComponent({
- status: 'creating',
- environment: null,
- });
-
- expect(findEnvironmentLink().exists()).toBe(false);
- });
- });
- });
-
- describe('with a cluster', () => {
- it('renders the cluster link', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- createDeploymentWithCluster(),
- );
-
- expect(findText()).toBe(
- `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
- );
-
- expect(findClusterLink().attributes('href')).toBe(TEST_CLUSTER_PATH);
- });
-
- describe('when the cluster is missing the path', () => {
- it('renders the name without a link', () => {
- createComponent(
- {
- status: 'last',
- environment: createEnvironmentWithLastDeployment(),
- },
- { name: 'the-cluster' },
- );
-
- expect(findText()).toContain('using cluster the-cluster.');
-
- expect(findClusterLink().exists()).toBe(false);
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/erased_block_spec.js b/spec/frontend/jobs/components/job/erased_block_spec.js
deleted file mode 100644
index aeab676fc7e..00000000000
--- a/spec/frontend/jobs/components/job/erased_block_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import ErasedBlock from '~/jobs/components/job/erased_block.vue';
-import { getTimeago } from '~/lib/utils/datetime_utility';
-
-describe('Erased block', () => {
- let wrapper;
-
- const erasedAt = '2016-11-07T11:11:16.525Z';
- const timeago = getTimeago();
- const formattedDate = timeago.format(erasedAt);
-
- const findLink = () => wrapper.findComponent(GlLink);
-
- const createComponent = (props) => {
- wrapper = mount(ErasedBlock, {
- propsData: props,
- });
- };
-
- describe('with job erased by user', () => {
- beforeEach(() => {
- createComponent({
- user: {
- username: 'root',
- web_url: 'gitlab.com/root',
- },
- erasedAt,
- });
- });
-
- it('renders username and link', () => {
- expect(findLink().attributes('href')).toEqual('gitlab.com/root');
-
- expect(wrapper.text().trim()).toContain('Job has been erased by');
- expect(wrapper.text().trim()).toContain('root');
- });
-
- it('renders erasedAt', () => {
- expect(wrapper.text().trim()).toContain(formattedDate);
- });
- });
-
- describe('with erased job', () => {
- beforeEach(() => {
- createComponent({
- erasedAt,
- });
- });
-
- it('renders username and link', () => {
- expect(wrapper.text().trim()).toContain('Job has been erased');
- });
-
- it('renders erasedAt', () => {
- expect(wrapper.text().trim()).toContain(formattedDate);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/job_app_spec.js b/spec/frontend/jobs/components/job/job_app_spec.js
deleted file mode 100644
index 8f5700ee22d..00000000000
--- a/spec/frontend/jobs/components/job/job_app_spec.js
+++ /dev/null
@@ -1,343 +0,0 @@
-import Vue, { nextTick } from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { TEST_HOST } from 'helpers/test_constants';
-import EmptyState from '~/jobs/components/job/empty_state.vue';
-import EnvironmentsBlock from '~/jobs/components/job/environments_block.vue';
-import ErasedBlock from '~/jobs/components/job/erased_block.vue';
-import JobApp from '~/jobs/components/job/job_app.vue';
-import JobLog from '~/jobs/components/log/log.vue';
-import JobLogTopBar from 'ee_else_ce/jobs/components/job/job_log_controllers.vue';
-import Sidebar from '~/jobs/components/job/sidebar/sidebar.vue';
-import StuckBlock from '~/jobs/components/job/stuck_block.vue';
-import UnmetPrerequisitesBlock from '~/jobs/components/job/unmet_prerequisites_block.vue';
-import createStore from '~/jobs/store';
-import axios from '~/lib/utils/axios_utils';
-import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
-import { MANUAL_STATUS } from '~/jobs/constants';
-import job from '../../mock_data';
-import { mockPendingJobData } from './mock_data';
-
-describe('Job App', () => {
- Vue.use(Vuex);
-
- let store;
- let wrapper;
- let mock;
-
- const initSettings = {
- endpoint: `${TEST_HOST}jobs/123.json`,
- pagePath: `${TEST_HOST}jobs/123`,
- logState:
- 'eyJvZmZzZXQiOjE3NDUxLCJuX29wZW5fdGFncyI6MCwiZmdfY29sb3IiOm51bGwsImJnX2NvbG9yIjpudWxsLCJzdHlsZV9tYXNrIjowfQ%3D%3D',
- };
-
- const props = {
- artifactHelpUrl: 'help/artifact',
- deploymentHelpUrl: 'help/deployment',
- runnerSettingsUrl: 'settings/ci-cd/runners',
- terminalPath: 'jobs/123/terminal',
- projectPath: 'user-name/project-name',
- subscriptionsMoreMinutesUrl: 'https://customers.gitlab.com/buy_pipeline_minutes',
- };
-
- const createComponent = () => {
- wrapper = shallowMountExtended(JobApp, {
- propsData: { ...props },
- store,
- });
- };
-
- const setupAndMount = async ({ jobData = {}, jobLogData = {} } = {}) => {
- mock.onGet(initSettings.endpoint).replyOnce(HTTP_STATUS_OK, { ...job, ...jobData });
- mock.onGet(`${initSettings.pagePath}/trace.json`).reply(HTTP_STATUS_OK, jobLogData);
-
- const asyncInit = store.dispatch('init', initSettings);
-
- createComponent();
-
- await asyncInit;
- jest.runOnlyPendingTimers();
- await axios.waitForAll();
- await nextTick();
- };
-
- const findLoadingComponent = () => wrapper.findComponent(GlLoadingIcon);
- const findSidebar = () => wrapper.findComponent(Sidebar);
- const findStuckBlockComponent = () => wrapper.findComponent(StuckBlock);
- const findFailedJobComponent = () => wrapper.findComponent(UnmetPrerequisitesBlock);
- const findEnvironmentsBlockComponent = () => wrapper.findComponent(EnvironmentsBlock);
- const findErasedBlock = () => wrapper.findComponent(ErasedBlock);
- const findEmptyState = () => wrapper.findComponent(EmptyState);
- const findJobLog = () => wrapper.findComponent(JobLog);
- const findJobLogTopBar = () => wrapper.findComponent(JobLogTopBar);
-
- const findJobContent = () => wrapper.findByTestId('job-content');
- const findArchivedJob = () => wrapper.findByTestId('archived-job');
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- store = createStore();
- });
-
- afterEach(() => {
- mock.restore();
- // eslint-disable-next-line @gitlab/vtu-no-explicit-wrapper-destroy
- wrapper.destroy();
- });
-
- describe('while loading', () => {
- beforeEach(() => {
- store.state.isLoading = true;
- createComponent();
- });
-
- it('renders loading icon', () => {
- expect(findLoadingComponent().exists()).toBe(true);
- expect(findSidebar().exists()).toBe(false);
- expect(findJobContent().exists()).toBe(false);
- });
- });
-
- describe('with successful request', () => {
- describe('Header section', () => {
- describe('job callout message', () => {
- 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', () =>
- setupAndMount({
- jobData: {
- callout_message: 'There is an unkown failure, please try again',
- },
- }).then(() => {
- expect(wrapper.vm.shouldRenderCalloutMessage).toBe(true);
- }));
- });
- });
-
- describe('stuck block', () => {
- describe('without active runners available', () => {
- it('renders stuck block when there are no runners', () =>
- setupAndMount({
- jobData: {
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- },
- stuck: true,
- runners: {
- available: false,
- online: false,
- },
- tags: [],
- },
- }).then(() => {
- expect(findStuckBlockComponent().exists()).toBe(true);
- }));
- });
-
- it('does not render stuck block when there are runners', () =>
- setupAndMount({
- jobData: {
- runners: { available: true },
- },
- }).then(() => {
- expect(findStuckBlockComponent().exists()).toBe(false);
- }));
- });
-
- describe('unmet prerequisites block', () => {
- it('renders unmet prerequisites block when there is an unmet prerequisites failure', () =>
- setupAndMount({
- jobData: {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- illustration: {
- content: 'Retry this job in order to create the necessary resources.',
- image: 'path',
- size: 'svg-430',
- title: 'Failed to create resources',
- },
- },
- failure_reason: 'unmet_prerequisites',
- has_trace: false,
- runners: {
- available: true,
- },
- tags: [],
- },
- }).then(() => {
- expect(findFailedJobComponent().exists()).toBe(true);
- }));
- });
-
- describe('environments block', () => {
- it('renders environment block when job has environment', () =>
- setupAndMount({
- jobData: {
- deployment_status: {
- environment: {
- environment_path: '/path',
- name: 'foo',
- },
- },
- },
- }).then(() => {
- expect(findEnvironmentsBlockComponent().exists()).toBe(true);
- }));
-
- it('does not render environment block when job has environment', () =>
- setupAndMount().then(() => {
- expect(findEnvironmentsBlockComponent().exists()).toBe(false);
- }));
- });
-
- describe('erased block', () => {
- it('renders erased block when `erased` is true', () =>
- setupAndMount({
- jobData: {
- erased_by: {
- username: 'root',
- web_url: 'gitlab.com/root',
- },
- erased_at: '2016-11-07T11:11:16.525Z',
- },
- }).then(() => {
- expect(findErasedBlock().exists()).toBe(true);
- }));
-
- it('does not render erased block when `erased` is false', () =>
- setupAndMount({
- jobData: {
- erased_at: null,
- },
- }).then(() => {
- expect(findErasedBlock().exists()).toBe(false);
- }));
- });
-
- describe('empty states block', () => {
- it('renders empty state when job does not have log and is not running', () =>
- setupAndMount({
- jobData: {
- has_trace: false,
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- illustration: {
- image: 'path',
- size: '340',
- title: 'Empty State',
- content: 'This is an empty state',
- },
- action: {
- button_title: 'Retry job',
- method: 'post',
- path: '/path',
- },
- },
- },
- }).then(() => {
- expect(findEmptyState().exists()).toBe(true);
- }));
-
- it('does not render empty state when job does not have log but it is running', () =>
- setupAndMount({
- jobData: {
- has_trace: false,
- status: {
- group: 'running',
- icon: 'status_running',
- label: 'running',
- text: 'running',
- details_path: 'path',
- },
- },
- }).then(() => {
- expect(findEmptyState().exists()).toBe(false);
- }));
-
- it('does not render empty state when job has log but it is not running', () =>
- setupAndMount({ jobData: { has_trace: true } }).then(() => {
- expect(findEmptyState().exists()).toBe(false);
- }));
- });
-
- describe('sidebar', () => {
- it('renders sidebar', async () => {
- await setupAndMount();
-
- expect(findSidebar().exists()).toBe(true);
- });
- });
- });
-
- describe('archived job', () => {
- beforeEach(() => setupAndMount({ jobData: { archived: true } }));
-
- it('renders warning about job being archived', () => {
- expect(findArchivedJob().exists()).toBe(true);
- });
- });
-
- describe('non-archived job', () => {
- beforeEach(() => setupAndMount());
-
- it('does not warning about job being archived', () => {
- expect(findArchivedJob().exists()).toBe(false);
- });
- });
-
- describe('job log', () => {
- beforeEach(() => setupAndMount());
-
- it('should render job log header', () => {
- expect(findJobLogTopBar().exists()).toBe(true);
- });
-
- it('should render job log', () => {
- expect(findJobLog().exists()).toBe(true);
- });
- });
-
- describe('job log polling', () => {
- beforeEach(() => {
- jest.spyOn(store, 'dispatch');
- });
-
- it('should poll job log by default', async () => {
- await setupAndMount({
- jobData: mockPendingJobData,
- });
-
- expect(store.dispatch).toHaveBeenCalledWith('fetchJobLog');
- });
-
- it('should NOT poll job log for manual variables form empty state', async () => {
- const manualPendingJobData = mockPendingJobData;
- manualPendingJobData.status.group = MANUAL_STATUS;
-
- await setupAndMount({
- jobData: manualPendingJobData,
- });
-
- expect(store.dispatch).not.toHaveBeenCalledWith('fetchJobLog');
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/job_container_item_spec.js b/spec/frontend/jobs/components/job/job_container_item_spec.js
deleted file mode 100644
index 39782130d38..00000000000
--- a/spec/frontend/jobs/components/job/job_container_item_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { GlIcon, GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import delayedJobFixture from 'test_fixtures/jobs/delayed.json';
-import JobContainerItem from '~/jobs/components/job/sidebar/job_container_item.vue';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import job from '../../mock_data';
-
-describe('JobContainerItem', () => {
- let wrapper;
-
- const findCiIcon = () => wrapper.findComponent(CiIcon);
- const findGlIcon = () => wrapper.findComponent(GlIcon);
-
- function createComponent(jobData = {}, props = { isActive: false, retried: false }) {
- wrapper = shallowMount(JobContainerItem, {
- propsData: {
- job: {
- ...jobData,
- retried: props.retried,
- },
- isActive: props.isActive,
- },
- });
- }
-
- describe('when a job is not active and not retried', () => {
- beforeEach(() => {
- createComponent(job);
- });
-
- it('displays a status icon', () => {
- expect(findCiIcon().props('status')).toBe(job.status);
- });
-
- it('displays the job name', () => {
- expect(wrapper.text()).toContain(job.name);
- });
-
- it('displays a link to the job', () => {
- const link = wrapper.findComponent(GlLink);
-
- expect(link.attributes('href')).toBe(job.status.details_path);
- });
- });
-
- describe('when a job is active', () => {
- beforeEach(() => {
- createComponent(job, { isActive: true });
- });
-
- it('displays an arrow sprite icon', () => {
- expect(findGlIcon().props('name')).toBe('arrow-right');
- });
- });
-
- describe('when a job is retried', () => {
- beforeEach(() => {
- createComponent(job, { isActive: false, retried: true });
- });
-
- it('displays a retry icon', () => {
- expect(findGlIcon().props('name')).toBe('retry');
- });
- });
-
- describe('for a delayed job', () => {
- beforeEach(() => {
- const remainingMilliseconds = 1337000;
- jest
- .spyOn(Date, 'now')
- .mockImplementation(
- () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingMilliseconds,
- );
-
- createComponent(delayedJobFixture);
- });
-
- it('displays remaining time in tooltip', async () => {
- await nextTick();
-
- const link = wrapper.findComponent(GlLink);
-
- expect(link.attributes('title')).toMatch('delayed job - delayed manual action (00:22:17)');
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/job_log_controllers_spec.js b/spec/frontend/jobs/components/job/job_log_controllers_spec.js
deleted file mode 100644
index 7b6d58f63d1..00000000000
--- a/spec/frontend/jobs/components/job/job_log_controllers_spec.js
+++ /dev/null
@@ -1,323 +0,0 @@
-import { GlSearchBoxByClick } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import JobLogControllers from '~/jobs/components/job/job_log_controllers.vue';
-import HelpPopover from '~/vue_shared/components/help_popover.vue';
-import { backoffMockImplementation } from 'helpers/backoff_helper';
-import * as commonUtils from '~/lib/utils/common_utils';
-import { mockJobLog } from '../../mock_data';
-
-const mockToastShow = jest.fn();
-
-describe('Job log controllers', () => {
- let wrapper;
-
- beforeEach(() => {
- jest.spyOn(commonUtils, 'backOff').mockImplementation(backoffMockImplementation);
- });
-
- afterEach(() => {
- commonUtils.backOff.mockReset();
- });
-
- const defaultProps = {
- rawPath: '/raw',
- size: 511952,
- isScrollTopDisabled: false,
- isScrollBottomDisabled: false,
- isScrollingDown: true,
- isJobLogSizeVisible: true,
- isComplete: true,
- jobLog: mockJobLog,
- };
-
- const createWrapper = (props, { jobLogJumpToFailures = false } = {}) => {
- wrapper = mount(JobLogControllers, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- provide: {
- glFeatures: {
- jobLogJumpToFailures,
- },
- },
- data() {
- return {
- searchTerm: '82',
- };
- },
- mocks: {
- $toast: {
- show: mockToastShow,
- },
- },
- });
- };
-
- 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 findScrollTop = () => wrapper.find('[data-testid="job-controller-scroll-top"]');
- const findScrollBottom = () => wrapper.find('[data-testid="job-controller-scroll-bottom"]');
- const findJobLogSearch = () => wrapper.findComponent(GlSearchBoxByClick);
- const findSearchHelp = () => wrapper.findComponent(HelpPopover);
- const findScrollFailure = () => wrapper.find('[data-testid="job-controller-scroll-to-failure"]');
-
- describe('Truncate information', () => {
- describe('with isJobLogSizeVisible', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('renders size information', () => {
- expect(findTruncatedInfo().text()).toMatch('499.95 KiB');
- });
-
- it('renders link to raw job log', () => {
- expect(findRawLink().attributes('href')).toBe(defaultProps.rawPath);
- });
- });
- });
-
- describe('links section', () => {
- describe('with raw job log path', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('renders raw job log link', () => {
- expect(findRawLinkController().attributes('href')).toBe(defaultProps.rawPath);
- });
- });
-
- describe('without raw job log path', () => {
- beforeEach(() => {
- createWrapper({
- rawPath: null,
- });
- });
-
- it('does not render raw job log link', () => {
- expect(findRawLinkController().exists()).toBe(false);
- });
- });
- });
-
- describe('scroll buttons', () => {
- describe('scroll top button', () => {
- describe('when user can scroll top', () => {
- beforeEach(() => {
- createWrapper({
- isScrollTopDisabled: false,
- });
- });
-
- it('emits scrollJobLogTop event on click', async () => {
- await findScrollTop().trigger('click');
-
- expect(wrapper.emitted().scrollJobLogTop).toHaveLength(1);
- });
- });
-
- describe('when user can not scroll top', () => {
- beforeEach(() => {
- createWrapper({
- isScrollTopDisabled: true,
- isScrollBottomDisabled: false,
- isScrollingDown: false,
- });
- });
-
- it('renders disabled scroll top button', () => {
- expect(findScrollTop().attributes('disabled')).toBeDefined();
- });
-
- it('does not emit scrollJobLogTop event on click', async () => {
- await findScrollTop().trigger('click');
-
- expect(wrapper.emitted().scrollJobLogTop).toBeUndefined();
- });
- });
- });
-
- describe('scroll bottom button', () => {
- describe('when user can scroll bottom', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('emits scrollJobLogBottom event on click', async () => {
- await findScrollBottom().trigger('click');
-
- expect(wrapper.emitted().scrollJobLogBottom).toHaveLength(1);
- });
- });
-
- describe('when user can not scroll bottom', () => {
- beforeEach(() => {
- createWrapper({
- isScrollTopDisabled: false,
- isScrollBottomDisabled: true,
- isScrollingDown: false,
- });
- });
-
- it('renders disabled scroll bottom button', () => {
- expect(findScrollBottom().attributes('disabled')).toEqual('disabled');
- });
-
- it('does not emit scrollJobLogBottom event on click', async () => {
- await findScrollBottom().trigger('click');
-
- expect(wrapper.emitted().scrollJobLogBottom).toBeUndefined();
- });
- });
-
- describe('while isScrollingDown is true', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('renders animate class for the scroll down button', () => {
- expect(findScrollBottom().classes()).toContain('animate');
- });
- });
-
- describe('while isScrollingDown is false', () => {
- beforeEach(() => {
- createWrapper({
- isScrollTopDisabled: true,
- isScrollBottomDisabled: false,
- isScrollingDown: false,
- });
- });
-
- it('does not render animate class for the scroll down button', () => {
- expect(findScrollBottom().classes()).not.toContain('animate');
- });
- });
- });
-
- describe('scroll to failure button', () => {
- describe('with feature flag disabled', () => {
- it('does not display button', () => {
- createWrapper();
-
- expect(findScrollFailure().exists()).toBe(false);
- });
- });
-
- describe('with red text failures on the page', () => {
- let firstFailure;
- let secondFailure;
-
- beforeEach(() => {
- jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce(['mock-element']);
-
- createWrapper({}, { jobLogJumpToFailures: true });
-
- firstFailure = document.createElement('div');
- firstFailure.className = 'term-fg-l-red';
- document.body.appendChild(firstFailure);
-
- secondFailure = document.createElement('div');
- secondFailure.className = 'term-fg-l-red';
- document.body.appendChild(secondFailure);
- });
-
- afterEach(() => {
- if (firstFailure) {
- firstFailure.remove();
- firstFailure = null;
- }
-
- if (secondFailure) {
- secondFailure.remove();
- secondFailure = null;
- }
- });
-
- it('is enabled', () => {
- expect(findScrollFailure().props('disabled')).toBe(false);
- });
-
- it('scrolls to each failure', async () => {
- jest.spyOn(firstFailure, 'scrollIntoView');
-
- await findScrollFailure().trigger('click');
-
- expect(firstFailure.scrollIntoView).toHaveBeenCalled();
-
- await findScrollFailure().trigger('click');
-
- expect(secondFailure.scrollIntoView).toHaveBeenCalled();
-
- await findScrollFailure().trigger('click');
-
- expect(firstFailure.scrollIntoView).toHaveBeenCalled();
- });
- });
-
- describe('with no red text failures on the page', () => {
- beforeEach(() => {
- jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce([]);
-
- createWrapper({}, { jobLogJumpToFailures: true });
- });
-
- it('is disabled', () => {
- expect(findScrollFailure().props('disabled')).toBe(true);
- });
- });
-
- describe('when the job log is not complete', () => {
- beforeEach(() => {
- jest.spyOn(document, 'querySelectorAll').mockReturnValueOnce(['mock-element']);
-
- createWrapper({ isComplete: false }, { jobLogJumpToFailures: true });
- });
-
- it('is enabled', () => {
- expect(findScrollFailure().props('disabled')).toBe(false);
- });
- });
-
- describe('on error', () => {
- beforeEach(() => {
- jest.spyOn(commonUtils, 'backOff').mockRejectedValueOnce();
-
- createWrapper({}, { jobLogJumpToFailures: true });
- });
-
- it('stays disabled', () => {
- expect(findScrollFailure().props('disabled')).toBe(true);
- });
- });
- });
- });
-
- describe('Job log search', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('displays job log search', () => {
- expect(findJobLogSearch().exists()).toBe(true);
- expect(findSearchHelp().exists()).toBe(true);
- });
-
- it('emits search results', () => {
- const expectedSearchResults = [[[mockJobLog[6].lines[1], mockJobLog[6].lines[2]]]];
-
- findJobLogSearch().vm.$emit('submit');
-
- expect(wrapper.emitted('searchResults')).toEqual(expectedSearchResults);
- });
-
- it('clears search results', () => {
- findJobLogSearch().vm.$emit('clear');
-
- expect(wrapper.emitted('searchResults')).toEqual([[[]]]);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/job_retry_forward_deployment_modal_spec.js b/spec/frontend/jobs/components/job/job_retry_forward_deployment_modal_spec.js
deleted file mode 100644
index a44a13259aa..00000000000
--- a/spec/frontend/jobs/components/job/job_retry_forward_deployment_modal_spec.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import { GlLink, GlModal } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import JobRetryForwardDeploymentModal from '~/jobs/components/job/sidebar/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.findComponent(GlLink);
- const findModal = () => wrapper.findComponent(GlModal);
-
- const createWrapper = ({ props = {}, provide = {}, stubs = {} } = {}) => {
- store = createStore();
- wrapper = shallowMount(JobRetryForwardDeploymentModal, {
- propsData: {
- modalId: 'modal-id',
- href: job.retry_path,
- ...props,
- },
- provide,
- store,
- stubs,
- });
- };
-
- 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/job_sidebar_details_container_spec.js b/spec/frontend/jobs/components/job/job_sidebar_details_container_spec.js
deleted file mode 100644
index c1028f3929d..00000000000
--- a/spec/frontend/jobs/components/job/job_sidebar_details_container_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import DetailRow from '~/jobs/components/job/sidebar/sidebar_detail_row.vue';
-import SidebarJobDetailsContainer from '~/jobs/components/job/sidebar/sidebar_job_details_container.vue';
-import createStore from '~/jobs/store';
-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.findAllComponents(DetailRow);
-
- const createWrapper = ({ props = {} } = {}) => {
- store = createStore();
- wrapper = extendedWrapper(
- shallowMount(SidebarJobDetailsContainer, {
- propsData: props,
- store,
- stubs: {
- DetailRow,
- },
- }),
- );
- };
-
- describe('when no details are available', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('should render an empty container', () => {
- expect(wrapper.html()).toBe('');
- });
-
- it.each(['duration', 'erased_at', 'finished_at', 'queued_at', 'runner', 'coverage'])(
- 'should not render %s details when missing',
- async (detail) => {
- await store.dispatch('receiveJobSuccess', { [detail]: undefined });
-
- expect(findAllDetailsRow()).toHaveLength(0);
- },
- );
- });
-
- describe('when some of the details are available', () => {
- beforeEach(createWrapper);
-
- it.each([
- ['duration', 'Elapsed time: 6 seconds'],
- ['erased_at', 'Erased: 3 weeks ago'],
- ['finished_at', 'Finished: 3 weeks ago'],
- ['queued_duration', 'Queued: 9 seconds'],
- ['runner', 'Runner: #1 (ABCDEFGH) local ci runner'],
- ['coverage', 'Coverage: 20%'],
- ])('uses %s to render job-%s', async (detail, value) => {
- await store.dispatch('receiveJobSuccess', { [detail]: job[detail] });
- const detailsRow = findAllDetailsRow();
-
- 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(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('duration row', () => {
- it('renders all the details components', async () => {
- createWrapper();
- await store.dispatch('receiveJobSuccess', job);
-
- expect(findAllDetailsRow().at(0).text()).toBe('Duration: 6 seconds');
- });
- });
- });
-
- 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.html()).toBe('');
- 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(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);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/job_sidebar_retry_button_spec.js b/spec/frontend/jobs/components/job/job_sidebar_retry_button_spec.js
deleted file mode 100644
index 8a63bfdc3d6..00000000000
--- a/spec/frontend/jobs/components/job/job_sidebar_retry_button_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import JobsSidebarRetryButton from '~/jobs/components/job/sidebar/job_sidebar_retry_button.vue';
-import createStore from '~/jobs/store';
-import job from '../../mock_data';
-
-describe('Job Sidebar Retry Button', () => {
- let store;
- let wrapper;
-
- const forwardDeploymentFailure = 'forward_deployment_failure';
- const findRetryButton = () => wrapper.findByTestId('retry-job-button');
- const findRetryLink = () => wrapper.findByTestId('retry-job-link');
-
- const createWrapper = ({ props = {} } = {}) => {
- store = createStore();
- wrapper = shallowMountExtended(JobsSidebarRetryButton, {
- propsData: {
- href: job.retry_path,
- isManualJob: false,
- modalId: 'modal-id',
- ...props,
- },
- store,
- });
- };
-
- 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);
- },
- );
-
- describe('Button', () => {
- it('should have the correct configuration', async () => {
- await store.dispatch('receiveJobSuccess', { failure_reason: forwardDeploymentFailure });
-
- expect(findRetryButton().attributes()).toMatchObject({
- category: 'primary',
- variant: 'confirm',
- icon: 'retry',
- });
- });
- });
-
- describe('Link', () => {
- it('should have the correct configuration', () => {
- expect(findRetryLink().attributes()).toMatchObject({
- 'data-method': 'post',
- href: job.retry_path,
- icon: 'retry',
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/jobs_container_spec.js b/spec/frontend/jobs/components/job/jobs_container_spec.js
deleted file mode 100644
index 05660880751..00000000000
--- a/spec/frontend/jobs/components/job/jobs_container_spec.js
+++ /dev/null
@@ -1,143 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import JobsContainer from '~/jobs/components/job/sidebar/jobs_container.vue';
-
-describe('Jobs List block', () => {
- let wrapper;
-
- const retried = {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 233432756,
- tooltip: 'build - passed',
- retried: true,
- };
-
- const active = {
- name: 'test',
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 2322756,
- tooltip: 'build - passed',
- active: true,
- };
-
- const job = {
- name: 'build',
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- id: 232153,
- tooltip: 'build - passed',
- };
-
- const findAllJobs = () => wrapper.findAllComponents(GlLink);
- const findJob = () => findAllJobs().at(0);
-
- const findArrowIcon = () => wrapper.findByTestId('arrow-right-icon');
- const findRetryIcon = () => wrapper.findByTestId('retry-icon');
-
- const createComponent = (props) => {
- wrapper = extendedWrapper(
- mount(JobsContainer, {
- propsData: {
- ...props,
- },
- }),
- );
- };
-
- it('renders a list of jobs', () => {
- createComponent({
- jobs: [job, retried, active],
- jobId: 12313,
- });
-
- expect(findAllJobs()).toHaveLength(3);
- });
-
- it('renders the arrow right icon when job id matches `jobId`', () => {
- createComponent({
- jobs: [active],
- jobId: active.id,
- });
-
- expect(findArrowIcon().exists()).toBe(true);
- });
-
- it('does not render the arrow right icon when the job is not active', () => {
- createComponent({
- jobs: [job],
- jobId: active.id,
- });
-
- expect(findArrowIcon().exists()).toBe(false);
- });
-
- it('renders the job name when present', () => {
- createComponent({
- jobs: [job],
- jobId: active.id,
- });
-
- expect(findJob().text()).toBe(job.name);
- expect(findJob().text()).not.toContain(job.id.toString());
- });
-
- it('renders job id when job name is not available', () => {
- createComponent({
- jobs: [retried],
- jobId: active.id,
- });
-
- expect(findJob().text()).toBe(retried.id.toString());
- });
-
- it('links to the job page', () => {
- createComponent({
- jobs: [job],
- jobId: active.id,
- });
-
- expect(findJob().attributes('href')).toBe(job.status.details_path);
- });
-
- it('renders retry icon when job was retried', () => {
- createComponent({
- jobs: [retried],
- jobId: active.id,
- });
-
- expect(findRetryIcon().exists()).toBe(true);
- });
-
- it('does not render retry icon when job was not retried', () => {
- createComponent({
- jobs: [job],
- jobId: active.id,
- });
-
- expect(findRetryIcon().exists()).toBe(false);
- });
-});
diff --git a/spec/frontend/jobs/components/job/manual_variables_form_spec.js b/spec/frontend/jobs/components/job/manual_variables_form_spec.js
deleted file mode 100644
index 989fe5c11e9..00000000000
--- a/spec/frontend/jobs/components/job/manual_variables_form_spec.js
+++ /dev/null
@@ -1,364 +0,0 @@
-import { GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
-import { createAlert } from '~/alert';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { TYPENAME_CI_BUILD } from '~/graphql_shared/constants';
-import { JOB_GRAPHQL_ERRORS } from '~/jobs/constants';
-import { convertToGraphQLId } from '~/graphql_shared/utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
-import ManualVariablesForm from '~/jobs/components/job/manual_variables_form.vue';
-import getJobQuery from '~/jobs/components/job/graphql/queries/get_job.query.graphql';
-import playJobMutation from '~/jobs/components/job/graphql/mutations/job_play_with_variables.mutation.graphql';
-import retryJobMutation from '~/jobs/components/job/graphql/mutations/job_retry_with_variables.mutation.graphql';
-
-import {
- mockFullPath,
- mockId,
- mockJobResponse,
- mockJobWithVariablesResponse,
- mockJobPlayMutationData,
- mockJobRetryMutationData,
-} from './mock_data';
-
-const localVue = createLocalVue();
-jest.mock('~/alert');
-localVue.use(VueApollo);
-
-jest.mock('~/lib/utils/url_utility', () => ({
- ...jest.requireActual('~/lib/utils/url_utility'),
- redirectTo: jest.fn(),
-}));
-
-const defaultProvide = {
- projectPath: mockFullPath,
-};
-
-describe('Manual Variables Form', () => {
- let wrapper;
- let mockApollo;
- let requestHandlers;
-
- const getJobQueryResponseHandlerWithVariables = jest.fn().mockResolvedValue(mockJobResponse);
- const playJobMutationHandler = jest.fn().mockResolvedValue({});
- const retryJobMutationHandler = jest.fn().mockResolvedValue({});
-
- const defaultHandlers = {
- getJobQueryResponseHandlerWithVariables,
- playJobMutationHandler,
- retryJobMutationHandler,
- };
-
- const createComponent = ({ props = {}, handlers = defaultHandlers } = {}) => {
- requestHandlers = handlers;
-
- mockApollo = createMockApollo([
- [getJobQuery, handlers.getJobQueryResponseHandlerWithVariables],
- [playJobMutation, handlers.playJobMutationHandler],
- [retryJobMutation, handlers.retryJobMutationHandler],
- ]);
-
- const options = {
- localVue,
- apolloProvider: mockApollo,
- };
-
- wrapper = mountExtended(ManualVariablesForm, {
- propsData: {
- jobId: mockId,
- isRetryable: false,
- ...props,
- },
- provide: {
- ...defaultProvide,
- },
- ...options,
- });
-
- return waitForPromises();
- };
-
- const findHelpText = () => wrapper.findComponent(GlSprintf);
- const findHelpLink = () => wrapper.findComponent(GlLink);
- const findCancelBtn = () => wrapper.findByTestId('cancel-btn');
- const findRunBtn = () => wrapper.findByTestId('run-manual-job-btn');
- const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn');
- const findAllDeleteVarBtns = () => wrapper.findAllByTestId('delete-variable-btn');
- const findDeleteVarBtnPlaceholder = () => wrapper.findByTestId('delete-variable-btn-placeholder');
- const findCiVariableKey = () => wrapper.findByTestId('ci-variable-key');
- const findAllCiVariableKeys = () => wrapper.findAllByTestId('ci-variable-key');
- const findCiVariableValue = () => wrapper.findByTestId('ci-variable-value');
- const findAllVariables = () => wrapper.findAllByTestId('ci-variable-row');
-
- const setCiVariableKey = () => {
- findCiVariableKey().setValue('new key');
- findCiVariableKey().vm.$emit('change');
- nextTick();
- };
-
- const setCiVariableKeyByPosition = (position, value) => {
- findAllCiVariableKeys().at(position).setValue(value);
- findAllCiVariableKeys().at(position).vm.$emit('change');
- nextTick();
- };
-
- afterEach(() => {
- createAlert.mockClear();
- });
-
- describe('when page renders', () => {
- beforeEach(async () => {
- await createComponent();
- });
-
- it('renders help text with provided link', () => {
- expect(findHelpText().exists()).toBe(true);
- expect(findHelpLink().attributes('href')).toBe(
- '/help/ci/variables/index#add-a-cicd-variable-to-a-project',
- );
- });
- });
-
- describe('when query is unsuccessful', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- getJobQueryResponseHandlerWithVariables: jest.fn().mockRejectedValue({}),
- },
- });
- });
-
- it('shows an alert with error', () => {
- expect(createAlert).toHaveBeenCalledWith({
- message: JOB_GRAPHQL_ERRORS.jobQueryErrorText,
- });
- });
- });
-
- describe('when job has not been retried', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- getJobQueryResponseHandlerWithVariables: jest
- .fn()
- .mockResolvedValue(mockJobWithVariablesResponse),
- },
- });
- });
-
- it('does not render the cancel button', () => {
- expect(findCancelBtn().exists()).toBe(false);
- expect(findRunBtn().exists()).toBe(true);
- });
- });
-
- describe('when job has variables', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- getJobQueryResponseHandlerWithVariables: jest
- .fn()
- .mockResolvedValue(mockJobWithVariablesResponse),
- },
- });
- });
-
- it('sets manual job variables', () => {
- const queryKey = mockJobWithVariablesResponse.data.project.job.manualVariables.nodes[0].key;
- const queryValue =
- mockJobWithVariablesResponse.data.project.job.manualVariables.nodes[0].value;
-
- expect(findCiVariableKey().element.value).toBe(queryKey);
- expect(findCiVariableValue().element.value).toBe(queryValue);
- });
- });
-
- describe('when play mutation fires', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- playJobMutationHandler: jest.fn().mockResolvedValue(mockJobPlayMutationData),
- },
- });
- });
-
- it('passes variables in correct format', async () => {
- await setCiVariableKey();
-
- await findCiVariableValue().setValue('new value');
-
- await findRunBtn().vm.$emit('click');
-
- expect(requestHandlers.playJobMutationHandler).toHaveBeenCalledTimes(1);
- expect(requestHandlers.playJobMutationHandler).toHaveBeenCalledWith({
- id: convertToGraphQLId(TYPENAME_CI_BUILD, mockId),
- variables: [
- {
- key: 'new key',
- value: 'new value',
- },
- ],
- });
- });
-
- it('redirects to job properly after job is run', async () => {
- findRunBtn().vm.$emit('click');
- await waitForPromises();
-
- expect(requestHandlers.playJobMutationHandler).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith(mockJobPlayMutationData.data.jobPlay.job.webPath); // eslint-disable-line import/no-deprecated
- });
- });
-
- describe('when play mutation is unsuccessful', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- playJobMutationHandler: jest.fn().mockRejectedValue({}),
- },
- });
- });
-
- it('shows an alert with error', async () => {
- findRunBtn().vm.$emit('click');
- await waitForPromises();
-
- expect(createAlert).toHaveBeenCalledWith({
- message: JOB_GRAPHQL_ERRORS.jobMutationErrorText,
- });
- });
- });
-
- describe('when job is retryable', () => {
- beforeEach(async () => {
- await createComponent({
- props: { isRetryable: true },
- handlers: {
- retryJobMutationHandler: jest.fn().mockResolvedValue(mockJobRetryMutationData),
- },
- });
- });
-
- it('renders cancel button', () => {
- expect(findCancelBtn().exists()).toBe(true);
- });
-
- it('redirects to job properly after rerun', async () => {
- findRunBtn().vm.$emit('click');
- await waitForPromises();
-
- expect(requestHandlers.retryJobMutationHandler).toHaveBeenCalledTimes(1);
- expect(redirectTo).toHaveBeenCalledWith(mockJobRetryMutationData.data.jobRetry.job.webPath); // eslint-disable-line import/no-deprecated
- });
- });
-
- describe('when retry mutation is unsuccessful', () => {
- beforeEach(async () => {
- await createComponent({
- props: { isRetryable: true },
- handlers: {
- retryJobMutationHandler: jest.fn().mockRejectedValue({}),
- },
- });
- });
-
- it('shows an alert with error', async () => {
- findRunBtn().vm.$emit('click');
- await waitForPromises();
-
- expect(createAlert).toHaveBeenCalledWith({
- message: JOB_GRAPHQL_ERRORS.jobMutationErrorText,
- });
- });
- });
-
- describe('updating variables in UI', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- getJobQueryResponseHandlerWithVariables: jest.fn().mockResolvedValue(mockJobResponse),
- },
- });
- });
-
- it('creates a new variable when user enters a new key value', async () => {
- expect(findAllVariables()).toHaveLength(1);
-
- await setCiVariableKey();
-
- expect(findAllVariables()).toHaveLength(2);
- });
-
- it('does not create extra empty variables', async () => {
- expect(findAllVariables()).toHaveLength(1);
-
- await setCiVariableKey();
-
- expect(findAllVariables()).toHaveLength(2);
-
- await setCiVariableKey();
-
- expect(findAllVariables()).toHaveLength(2);
- });
-
- it('removes the correct variable row', async () => {
- const variableKeyNameOne = 'key-one';
- const variableKeyNameThree = 'key-three';
-
- await setCiVariableKeyByPosition(0, variableKeyNameOne);
-
- await setCiVariableKeyByPosition(1, 'key-two');
-
- await setCiVariableKeyByPosition(2, variableKeyNameThree);
-
- expect(findAllVariables()).toHaveLength(4);
-
- await findAllDeleteVarBtns().at(1).trigger('click');
-
- expect(findAllVariables()).toHaveLength(3);
-
- expect(findAllCiVariableKeys().at(0).element.value).toBe(variableKeyNameOne);
- expect(findAllCiVariableKeys().at(1).element.value).toBe(variableKeyNameThree);
- expect(findAllCiVariableKeys().at(2).element.value).toBe('');
- });
-
- it('delete variable button should only show when there is more than one variable', async () => {
- expect(findDeleteVarBtn().exists()).toBe(false);
-
- await setCiVariableKey();
-
- expect(findDeleteVarBtn().exists()).toBe(true);
- });
- });
-
- describe('variable delete button placeholder', () => {
- beforeEach(async () => {
- await createComponent({
- handlers: {
- getJobQueryResponseHandlerWithVariables: jest.fn().mockResolvedValue(mockJobResponse),
- },
- });
- });
-
- it('delete variable button placeholder should only exist when a user cannot remove', () => {
- expect(findDeleteVarBtnPlaceholder().exists()).toBe(true);
- });
-
- it('does not show the placeholder button', () => {
- expect(findDeleteVarBtnPlaceholder().classes('gl-opacity-0')).toBe(true);
- });
-
- it('placeholder button will not delete the row on click', async () => {
- expect(findAllCiVariableKeys()).toHaveLength(1);
- expect(findDeleteVarBtnPlaceholder().exists()).toBe(true);
-
- await findDeleteVarBtnPlaceholder().trigger('click');
-
- expect(findAllCiVariableKeys()).toHaveLength(1);
- expect(findDeleteVarBtnPlaceholder().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/mock_data.js b/spec/frontend/jobs/components/job/mock_data.js
deleted file mode 100644
index fb3a361c9c9..00000000000
--- a/spec/frontend/jobs/components/job/mock_data.js
+++ /dev/null
@@ -1,123 +0,0 @@
-export const mockFullPath = 'Commit451/lab-coat';
-export const mockId = 401;
-
-export const mockJobResponse = {
- data: {
- project: {
- id: 'gid://gitlab/Project/4',
- job: {
- id: 'gid://gitlab/Ci::Build/401',
- manualJob: true,
- manualVariables: {
- nodes: [],
- __typename: 'CiManualVariableConnection',
- },
- name: 'manual_job',
- retryable: true,
- status: 'SUCCESS',
- __typename: 'CiJob',
- },
- __typename: 'Project',
- },
- },
-};
-
-export const mockJobWithVariablesResponse = {
- data: {
- project: {
- id: 'gid://gitlab/Project/4',
- job: {
- id: 'gid://gitlab/Ci::Build/401',
- manualJob: true,
- manualVariables: {
- nodes: [
- {
- id: 'gid://gitlab/Ci::JobVariable/150',
- key: 'new key',
- value: 'new value',
- __typename: 'CiManualVariable',
- },
- ],
- __typename: 'CiManualVariableConnection',
- },
- name: 'manual_job',
- retryable: true,
- status: 'SUCCESS',
- __typename: 'CiJob',
- },
- __typename: 'Project',
- },
- },
-};
-
-export const mockJobPlayMutationData = {
- data: {
- jobPlay: {
- job: {
- id: 'gid://gitlab/Ci::Build/401',
- manualVariables: {
- nodes: [
- {
- id: 'gid://gitlab/Ci::JobVariable/151',
- key: 'new key',
- value: 'new value',
- __typename: 'CiManualVariable',
- },
- ],
- __typename: 'CiManualVariableConnection',
- },
- webPath: '/Commit451/lab-coat/-/jobs/401',
- __typename: 'CiJob',
- },
- errors: [],
- __typename: 'JobPlayPayload',
- },
- },
-};
-
-export const mockJobRetryMutationData = {
- data: {
- jobRetry: {
- job: {
- id: 'gid://gitlab/Ci::Build/401',
- manualVariables: {
- nodes: [
- {
- id: 'gid://gitlab/Ci::JobVariable/151',
- key: 'new key',
- value: 'new value',
- __typename: 'CiManualVariable',
- },
- ],
- __typename: 'CiManualVariableConnection',
- },
- webPath: '/Commit451/lab-coat/-/jobs/401',
- __typename: 'CiJob',
- },
- errors: [],
- __typename: 'JobRetryPayload',
- },
- },
-};
-
-export const mockPendingJobData = {
- has_trace: false,
- status: {
- group: 'pending',
- icon: 'status_pending',
- label: 'pending',
- text: 'pending',
- details_path: 'path',
- illustration: {
- image: 'path',
- size: '340',
- title: '',
- content: '',
- },
- action: {
- button_title: 'Retry job',
- method: 'post',
- path: '/path',
- },
- },
-};
diff --git a/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js b/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js
deleted file mode 100644
index 546f5392caf..00000000000
--- a/spec/frontend/jobs/components/job/sidebar_detail_row_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import SidebarDetailRow from '~/jobs/components/job/sidebar/sidebar_detail_row.vue';
-import { DOCS_URL } from 'jh_else_ce/lib/utils/url_utility';
-
-describe('Sidebar detail row', () => {
- let wrapper;
-
- const title = 'this is the title';
- const value = 'this is the value';
- const helpUrl = `${DOCS_URL}/runner/register/index.html`;
- const path = 'path/to/value';
-
- const findHelpLink = () => wrapper.findByTestId('job-sidebar-help-link');
- const findValueLink = () => wrapper.findByTestId('job-sidebar-value-link');
-
- const createComponent = (props) => {
- wrapper = shallowMountExtended(SidebarDetailRow, {
- propsData: {
- ...props,
- },
- });
- };
-
- describe('with title/value and without helpUrl/path', () => {
- beforeEach(() => {
- createComponent({ title, value });
- });
-
- it('should render the provided title and value', () => {
- expect(wrapper.text()).toBe(`${title}: ${value}`);
- });
-
- it('should not render the help link', () => {
- expect(findHelpLink().exists()).toBe(false);
- });
-
- it('should not render the value link', () => {
- expect(findValueLink().exists()).toBe(false);
- });
- });
-
- describe('when helpUrl provided', () => {
- beforeEach(() => {
- createComponent({
- helpUrl,
- title,
- value,
- });
- });
-
- it('should render the help link', () => {
- expect(findHelpLink().exists()).toBe(true);
- expect(findHelpLink().attributes('href')).toBe(helpUrl);
- });
- });
-
- describe('when path is provided', () => {
- it('should render link to value', () => {
- createComponent({
- path,
- title,
- value,
- });
-
- expect(findValueLink().attributes('href')).toBe(path);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/sidebar_header_spec.js b/spec/frontend/jobs/components/job/sidebar_header_spec.js
deleted file mode 100644
index cf182330578..00000000000
--- a/spec/frontend/jobs/components/job/sidebar_header_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import SidebarHeader from '~/jobs/components/job/sidebar/sidebar_header.vue';
-import JobRetryButton from '~/jobs/components/job/sidebar/job_sidebar_retry_button.vue';
-import getJobQuery from '~/jobs/components/job/graphql/queries/get_job.query.graphql';
-import { mockFullPath, mockId, mockJobResponse } from './mock_data';
-
-Vue.use(VueApollo);
-
-const defaultProvide = {
- projectPath: mockFullPath,
-};
-
-describe('Sidebar Header', () => {
- let wrapper;
-
- const createComponent = ({ options = {}, props = {}, restJob = {} } = {}) => {
- wrapper = shallowMountExtended(SidebarHeader, {
- propsData: {
- ...props,
- jobId: mockId,
- restJob,
- },
- provide: {
- ...defaultProvide,
- },
- ...options,
- });
- };
-
- const createComponentWithApollo = ({ props = {}, restJob = {} } = {}) => {
- const getJobQueryResponse = jest.fn().mockResolvedValue(mockJobResponse);
-
- const requestHandlers = [[getJobQuery, getJobQueryResponse]];
-
- const apolloProvider = createMockApollo(requestHandlers);
-
- const options = {
- apolloProvider,
- };
-
- createComponent({
- props,
- restJob,
- options,
- });
-
- return waitForPromises();
- };
-
- const findCancelButton = () => wrapper.findByTestId('cancel-button');
- const findEraseButton = () => wrapper.findByTestId('job-log-erase-link');
- const findJobName = () => wrapper.findByTestId('job-name');
- const findRetryButton = () => wrapper.findComponent(JobRetryButton);
-
- describe('when rendering contents', () => {
- it('renders the correct job name', async () => {
- await createComponentWithApollo();
- expect(findJobName().text()).toBe(mockJobResponse.data.project.job.name);
- });
-
- it('does not render buttons with no paths', async () => {
- await createComponentWithApollo();
- expect(findCancelButton().exists()).toBe(false);
- expect(findEraseButton().exists()).toBe(false);
- expect(findRetryButton().exists()).toBe(false);
- });
-
- it('renders a retry button with a path', async () => {
- await createComponentWithApollo({ restJob: { retry_path: 'retry/path' } });
- expect(findRetryButton().exists()).toBe(true);
- });
-
- it('renders a cancel button with a path', async () => {
- await createComponentWithApollo({ restJob: { cancel_path: 'cancel/path' } });
- expect(findCancelButton().exists()).toBe(true);
- });
-
- it('renders an erase button with a path', async () => {
- await createComponentWithApollo({ restJob: { erase_path: 'erase/path' } });
- expect(findEraseButton().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/sidebar_spec.js b/spec/frontend/jobs/components/job/sidebar_spec.js
deleted file mode 100644
index fbff64b4d78..00000000000
--- a/spec/frontend/jobs/components/job/sidebar_spec.js
+++ /dev/null
@@ -1,216 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import MockAdapter from 'axios-mock-adapter';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import axios from '~/lib/utils/axios_utils';
-import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
-import ArtifactsBlock from '~/jobs/components/job/sidebar/artifacts_block.vue';
-import JobRetryForwardDeploymentModal from '~/jobs/components/job/sidebar/job_retry_forward_deployment_modal.vue';
-import JobsContainer from '~/jobs/components/job/sidebar/jobs_container.vue';
-import Sidebar from '~/jobs/components/job/sidebar/sidebar.vue';
-import StagesDropdown from '~/jobs/components/job/sidebar/stages_dropdown.vue';
-import createStore from '~/jobs/store';
-import job, { jobsInStage } from '../../mock_data';
-
-describe('Sidebar details block', () => {
- let mock;
- let store;
- let wrapper;
-
- const forwardDeploymentFailure = 'forward_deployment_failure';
- const findModal = () => wrapper.findComponent(JobRetryForwardDeploymentModal);
- const findArtifactsBlock = () => wrapper.findComponent(ArtifactsBlock);
- const findNewIssueButton = () => wrapper.findByTestId('job-new-issue');
- const findTerminalLink = () => wrapper.findByTestId('terminal-link');
- const findJobStagesDropdown = () => wrapper.findComponent(StagesDropdown);
- const findJobsContainer = () => wrapper.findComponent(JobsContainer);
-
- const createWrapper = (props) => {
- store = createStore();
-
- store.state.job = job;
-
- wrapper = extendedWrapper(
- shallowMount(Sidebar, {
- propsData: {
- ...props,
- },
-
- store,
- }),
- );
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet().reply(HTTP_STATUS_OK, {
- name: job.stage,
- });
- });
-
- describe('without terminal path', () => {
- it('does not render terminal link', async () => {
- createWrapper();
- await store.dispatch('receiveJobSuccess', job);
-
- expect(findTerminalLink().exists()).toBe(false);
- });
- });
-
- describe('with terminal path', () => {
- it('renders terminal link', async () => {
- createWrapper();
- await store.dispatch('receiveJobSuccess', { ...job, terminal_path: 'job/43123/terminal' });
-
- expect(findTerminalLink().exists()).toBe(true);
- });
- });
-
- describe('actions', () => {
- beforeEach(() => {
- createWrapper();
- return store.dispatch('receiveJobSuccess', job);
- });
-
- it('should render link to new issue', () => {
- expect(findNewIssueButton().attributes('href')).toBe(job.new_issue_path);
- expect(findNewIssueButton().text()).toBe('New issue');
- });
- });
-
- 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);
- },
- );
- });
-
- describe('when there is the relevant error', () => {
- beforeEach(() => {
- createWrapper();
- return store.dispatch('receiveJobSuccess', {
- ...job,
- failure_reason: forwardDeploymentFailure,
- });
- });
-
- it('should render the modal', () => {
- expect(findModal().exists()).toBe(true);
- });
- });
- });
-
- describe('stages dropdown', () => {
- beforeEach(() => {
- createWrapper();
- return store.dispatch('receiveJobSuccess', job);
- });
-
- describe('with stages', () => {
- it('renders value provided as selectedStage as selected', () => {
- expect(findJobStagesDropdown().props('selectedStage')).toBe(job.stage);
- });
- });
-
- describe('without jobs for stages', () => {
- it('does not render jobs container', () => {
- expect(findJobsContainer().exists()).toBe(false);
- });
- });
-
- describe('with jobs for stages', () => {
- beforeEach(() => {
- return store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
- });
-
- it('renders list of jobs', () => {
- expect(findJobsContainer().exists()).toBe(true);
- });
- });
-
- describe('when job data changes', () => {
- const stageArg = job.pipeline.details.stages.find((stage) => stage.name === job.stage);
-
- beforeEach(() => {
- jest.spyOn(store, 'dispatch');
- });
-
- describe('and the job stage is currently selected', () => {
- describe('when the status changed', () => {
- it('refetch the jobs list for the stage', async () => {
- await store.dispatch('receiveJobSuccess', { ...job, status: 'new' });
-
- expect(store.dispatch).toHaveBeenNthCalledWith(2, 'fetchJobsForStage', { ...stageArg });
- });
- });
-
- describe('when the status did not change', () => {
- it('does not refetch the jobs list for the stage', async () => {
- await store.dispatch('receiveJobSuccess', { ...job });
-
- expect(store.dispatch).toHaveBeenCalledTimes(1);
- expect(store.dispatch).toHaveBeenNthCalledWith(1, 'receiveJobSuccess', {
- ...job,
- });
- });
- });
- });
-
- describe('and the job stage is not currently selected', () => {
- it('does not refetch the jobs list for the stage', async () => {
- // Setting stage to `random` on the job means that we are looking
- // at `build` stage currently, but the job we are seeing in the logs
- // belong to `random`, so we shouldn't have to refetch
- await store.dispatch('receiveJobSuccess', { ...job, stage: 'random' });
-
- expect(store.dispatch).toHaveBeenCalledTimes(1);
- expect(store.dispatch).toHaveBeenNthCalledWith(1, 'receiveJobSuccess', {
- ...job,
- stage: 'random',
- });
- });
- });
- });
- });
-
- describe('artifacts', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('artifacts are not shown if there are no properties other than locked', () => {
- expect(findArtifactsBlock().exists()).toBe(false);
- });
-
- it('artifacts are shown if present', async () => {
- store.state.job.artifact = {
- download_path: '/root/ci-project/-/jobs/1960/artifacts/download',
- browse_path: '/root/ci-project/-/jobs/1960/artifacts/browse',
- keep_path: '/root/ci-project/-/jobs/1960/artifacts/keep',
- expire_at: '2021-03-23T17:57:11.211Z',
- expired: false,
- locked: false,
- };
-
- await nextTick();
-
- expect(findArtifactsBlock().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/stages_dropdown_spec.js b/spec/frontend/jobs/components/job/stages_dropdown_spec.js
deleted file mode 100644
index c42edc62183..00000000000
--- a/spec/frontend/jobs/components/job/stages_dropdown_spec.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import { GlDisclosureDropdown, GlLink, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { Mousetrap } from '~/lib/mousetrap';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import StagesDropdown from '~/jobs/components/job/sidebar/stages_dropdown.vue';
-import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import * as copyToClipboard from '~/behaviors/copy_to_clipboard';
-import {
- mockPipelineWithoutRef,
- mockPipelineWithoutMR,
- mockPipelineWithAttachedMR,
- mockPipelineDetached,
-} from '../../mock_data';
-
-describe('Stages Dropdown', () => {
- let wrapper;
-
- const findStatus = () => wrapper.findComponent(CiIcon);
- const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
- const findSelectedStageText = () => findDropdown().props('toggleText');
-
- const findPipelineInfoText = () => wrapper.findByTestId('pipeline-info').text();
-
- const createComponent = (props) => {
- wrapper = extendedWrapper(
- shallowMount(StagesDropdown, {
- propsData: {
- stages: [],
- selectedStage: 'deploy',
- ...props,
- },
- stubs: {
- GlSprintf,
- GlLink,
- },
- }),
- );
- };
-
- describe('without a merge request pipeline', () => {
- beforeEach(() => {
- createComponent({
- pipeline: mockPipelineWithoutMR,
- stages: [{ name: 'build' }, { name: 'test' }],
- });
- });
-
- it('renders pipeline status', () => {
- expect(findStatus().exists()).toBe(true);
- });
-
- it('renders dropdown with stages', () => {
- expect(findDropdown().props('items')).toEqual([
- expect.objectContaining({ text: 'build' }),
- expect.objectContaining({ text: 'test' }),
- ]);
- });
-
- it('renders selected stage', () => {
- expect(findSelectedStageText()).toBe('deploy');
- });
- });
-
- describe('pipelineInfo', () => {
- const allElements = [
- 'pipeline-path',
- 'mr-link',
- 'source-ref-link',
- 'copy-source-ref-link',
- 'source-branch-link',
- 'copy-source-branch-link',
- 'target-branch-link',
- 'copy-target-branch-link',
- ];
- describe.each([
- [
- 'does not have a ref',
- {
- pipeline: mockPipelineWithoutRef,
- text: `Pipeline #${mockPipelineWithoutRef.id}`,
- foundElements: [
- { testId: 'pipeline-path', props: [{ href: mockPipelineWithoutRef.path }] },
- ],
- },
- ],
- [
- 'hasRef but not triggered by MR',
- {
- pipeline: mockPipelineWithoutMR,
- text: `Pipeline #${mockPipelineWithoutMR.id} for ${mockPipelineWithoutMR.ref.name}`,
- foundElements: [
- { testId: 'pipeline-path', props: [{ href: mockPipelineWithoutMR.path }] },
- { testId: 'source-ref-link', props: [{ href: mockPipelineWithoutMR.ref.path }] },
- { testId: 'copy-source-ref-link', props: [{ text: mockPipelineWithoutMR.ref.name }] },
- ],
- },
- ],
- [
- 'hasRef and MR but not MR pipeline',
- {
- pipeline: mockPipelineDetached,
- text: `Pipeline #${mockPipelineDetached.id} for !${mockPipelineDetached.merge_request.iid} with ${mockPipelineDetached.merge_request.source_branch}`,
- foundElements: [
- { testId: 'pipeline-path', props: [{ href: mockPipelineDetached.path }] },
- { testId: 'mr-link', props: [{ href: mockPipelineDetached.merge_request.path }] },
- {
- testId: 'source-branch-link',
- props: [{ href: mockPipelineDetached.merge_request.source_branch_path }],
- },
- {
- testId: 'copy-source-branch-link',
- props: [{ text: mockPipelineDetached.merge_request.source_branch }],
- },
- ],
- },
- ],
- [
- 'hasRef and MR and MR pipeline',
- {
- pipeline: mockPipelineWithAttachedMR,
- text: `Pipeline #${mockPipelineWithAttachedMR.id} for !${mockPipelineWithAttachedMR.merge_request.iid} with ${mockPipelineWithAttachedMR.merge_request.source_branch} into ${mockPipelineWithAttachedMR.merge_request.target_branch}`,
- foundElements: [
- { testId: 'pipeline-path', props: [{ href: mockPipelineWithAttachedMR.path }] },
- { testId: 'mr-link', props: [{ href: mockPipelineWithAttachedMR.merge_request.path }] },
- {
- testId: 'source-branch-link',
- props: [{ href: mockPipelineWithAttachedMR.merge_request.source_branch_path }],
- },
- {
- testId: 'copy-source-branch-link',
- props: [{ text: mockPipelineWithAttachedMR.merge_request.source_branch }],
- },
- {
- testId: 'target-branch-link',
- props: [{ href: mockPipelineWithAttachedMR.merge_request.target_branch_path }],
- },
- {
- testId: 'copy-target-branch-link',
- props: [{ text: mockPipelineWithAttachedMR.merge_request.target_branch }],
- },
- ],
- },
- ],
- ])('%s', (_, { pipeline, text, foundElements }) => {
- beforeEach(() => {
- createComponent({
- pipeline,
- });
- });
-
- it('should render the text', () => {
- expect(findPipelineInfoText()).toMatchInterpolatedText(text);
- });
-
- it('should find components with props', () => {
- foundElements.forEach((element) => {
- element.props.forEach((prop) => {
- const key = Object.keys(prop)[0];
- expect(wrapper.findByTestId(element.testId).attributes(key)).toBe(prop[key]);
- });
- });
- });
-
- it('should not find components', () => {
- const foundTestIds = foundElements.map((element) => element.testId);
- allElements
- .filter((testId) => !foundTestIds.includes(testId))
- .forEach((testId) => {
- expect(wrapper.findByTestId(testId).exists()).toBe(false);
- });
- });
- });
- });
-
- describe('mousetrap', () => {
- it.each([
- ['copy-source-ref-link', mockPipelineWithoutMR],
- ['copy-source-branch-link', mockPipelineWithAttachedMR],
- ])(
- 'calls clickCopyToClipboardButton with `%s` button when `b` is pressed',
- (button, pipeline) => {
- const copyToClipboardMock = jest.spyOn(copyToClipboard, 'clickCopyToClipboardButton');
- createComponent({ pipeline });
-
- Mousetrap.trigger('b');
-
- expect(copyToClipboardMock).toHaveBeenCalledWith(wrapper.findByTestId(button).element);
- },
- );
- });
-});
diff --git a/spec/frontend/jobs/components/job/stuck_block_spec.js b/spec/frontend/jobs/components/job/stuck_block_spec.js
deleted file mode 100644
index 0f014a9222b..00000000000
--- a/spec/frontend/jobs/components/job/stuck_block_spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import { GlBadge, GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import StuckBlock from '~/jobs/components/job/stuck_block.vue';
-
-describe('Stuck Block Job component', () => {
- let wrapper;
-
- 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.findComponent(GlLink);
- const findAllBadges = () => wrapper.findAllComponents(GlBadge);
-
- describe('with no runners for project', () => {
- beforeEach(() => {
- createWrapper({
- hasOfflineRunnersForProject: true,
- runnersPath: '/root/project/runners#js-runners-settings',
- });
- });
-
- it('renders only information about project not having runners', () => {
- expect(findStuckNoRunners().exists()).toBe(true);
- expect(findStuckWithTags().exists()).toBe(false);
- expect(findStuckNoActiveRunners().exists()).toBe(false);
- });
-
- it('renders link to runners page', () => {
- expect(findRunnerPathLink().attributes('href')).toBe(
- '/root/project/runners#js-runners-settings',
- );
- });
- });
-
- describe('with tags', () => {
- beforeEach(() => {
- createWrapper({
- hasOfflineRunnersForProject: false,
- tags,
- runnersPath: '/root/project/runners#js-runners-settings',
- });
- });
-
- it('renders information about the tags not being set', () => {
- expect(findStuckWithTags().exists()).toBe(true);
- expect(findStuckNoActiveRunners().exists()).toBe(false);
- expect(findStuckNoRunners().exists()).toBe(false);
- });
-
- it('renders tags', () => {
- findAllBadges().wrappers.forEach((badgeElt, index) => {
- return expect(badgeElt.text()).toBe(tags[index]);
- });
- });
-
- it('renders link to runners page', () => {
- expect(findRunnerPathLink().attributes('href')).toBe(
- '/root/project/runners#js-runners-settings',
- );
- });
- });
-
- describe('without active runners', () => {
- beforeEach(() => {
- createWrapper({
- hasOfflineRunnersForProject: false,
- runnersPath: '/root/project/runners#js-runners-settings',
- });
- });
-
- it('renders information about project not having runners', () => {
- expect(findStuckNoActiveRunners().exists()).toBe(true);
- expect(findStuckNoRunners().exists()).toBe(false);
- expect(findStuckWithTags().exists()).toBe(false);
- });
-
- it('renders link to runners page', () => {
- expect(findRunnerPathLink().attributes('href')).toBe(
- '/root/project/runners#js-runners-settings',
- );
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/trigger_block_spec.js b/spec/frontend/jobs/components/job/trigger_block_spec.js
deleted file mode 100644
index 8bb2c1f3ad8..00000000000
--- a/spec/frontend/jobs/components/job/trigger_block_spec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import { GlButton, GlTableLite } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import TriggerBlock from '~/jobs/components/job/sidebar/trigger_block.vue';
-
-describe('Trigger block', () => {
- let wrapper;
-
- const findRevealButton = () => wrapper.findComponent(GlButton);
- const findVariableTable = () => wrapper.findComponent(GlTableLite);
- const findShortToken = () => wrapper.find('[data-testid="trigger-short-token"]');
- const findVariableValue = (index) =>
- wrapper.findAll('[data-testid="trigger-build-value"]').at(index);
- const findVariableKey = (index) => wrapper.findAll('[data-testid="trigger-build-key"]').at(index);
-
- const createComponent = (props) => {
- wrapper = mount(TriggerBlock, {
- propsData: {
- ...props,
- },
- });
- };
-
- describe('with short token and no variables', () => {
- it('renders short token', () => {
- createComponent({
- trigger: {
- short_token: '0a666b2',
- variables: [],
- },
- });
-
- expect(findShortToken().text()).toContain('0a666b2');
- });
- });
-
- describe('without variables or short token', () => {
- beforeEach(() => {
- createComponent({ trigger: { variables: [] } });
- });
-
- it('does not render short token', () => {
- expect(findShortToken().exists()).toBe(false);
- });
-
- it('does not render variables', () => {
- expect(findRevealButton().exists()).toBe(false);
- expect(findVariableTable().exists()).toBe(false);
- });
- });
-
- describe('with variables', () => {
- describe('hide/reveal variables', () => {
- it('should toggle variables on click', async () => {
- const hiddenValue = '••••••';
- const gcsVar = { key: 'UPLOAD_TO_GCS', value: 'false', public: false };
- const s3Var = { key: 'UPLOAD_TO_S3', value: 'true', public: false };
-
- createComponent({
- trigger: {
- variables: [gcsVar, s3Var],
- },
- });
-
- expect(findRevealButton().text()).toBe('Reveal values');
-
- expect(findVariableValue(0).text()).toBe(hiddenValue);
- expect(findVariableValue(1).text()).toBe(hiddenValue);
-
- expect(findVariableKey(0).text()).toBe(gcsVar.key);
- expect(findVariableKey(1).text()).toBe(s3Var.key);
-
- await findRevealButton().trigger('click');
-
- expect(findRevealButton().text()).toBe('Hide values');
-
- expect(findVariableValue(0).text()).toBe(gcsVar.value);
- expect(findVariableValue(1).text()).toBe(s3Var.value);
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/job/unmet_prerequisites_block_spec.js b/spec/frontend/jobs/components/job/unmet_prerequisites_block_spec.js
deleted file mode 100644
index 1072cdd6781..00000000000
--- a/spec/frontend/jobs/components/job/unmet_prerequisites_block_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { GlAlert, GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import UnmetPrerequisitesBlock from '~/jobs/components/job/unmet_prerequisites_block.vue';
-
-describe('Unmet Prerequisites Block Job component', () => {
- let wrapper;
- const helpPath = '/user/project/clusters/index.html#troubleshooting-failed-deployment-jobs';
-
- const createComponent = () => {
- wrapper = shallowMount(UnmetPrerequisitesBlock, {
- propsData: {
- helpPath,
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- it('renders an alert with the correct message', () => {
- const container = wrapper.findComponent(GlAlert);
- const alertMessage =
- 'This job failed because the necessary resources were not successfully created.';
-
- expect(container).not.toBeNull();
- expect(container.text()).toContain(alertMessage);
- });
-
- it('renders link to help page', () => {
- const helpLink = wrapper.findComponent(GlLink);
-
- expect(helpLink).not.toBeNull();
- expect(helpLink.text()).toContain('More information');
- expect(helpLink.attributes().href).toEqual(helpPath);
- });
-});
diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js
deleted file mode 100644
index 5adedea28a5..00000000000
--- a/spec/frontend/jobs/components/log/collapsible_section_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import CollapsibleSection from '~/jobs/components/log/collapsible_section.vue';
-import { collapsibleSectionClosed, collapsibleSectionOpened } from './mock_data';
-
-describe('Job Log Collapsible Section', () => {
- let wrapper;
-
- const jobLogEndpoint = 'jobs/335';
-
- const findCollapsibleLine = () => wrapper.find('.collapsible-line');
- const findCollapsibleLineSvg = () => wrapper.find('.collapsible-line svg');
-
- const createComponent = (props = {}) => {
- wrapper = mount(CollapsibleSection, {
- propsData: {
- ...props,
- },
- });
- };
-
- describe('with closed section', () => {
- beforeEach(() => {
- createComponent({
- section: collapsibleSectionClosed,
- jobLogEndpoint,
- });
- });
-
- it('renders clickable header line', () => {
- expect(findCollapsibleLine().attributes('role')).toBe('button');
- });
-
- it('renders an icon with the closed state', () => {
- expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('chevron-lg-right-icon');
- });
- });
-
- describe('with opened section', () => {
- beforeEach(() => {
- createComponent({
- section: collapsibleSectionOpened,
- jobLogEndpoint,
- });
- });
-
- it('renders clickable header line', () => {
- expect(findCollapsibleLine().attributes('role')).toBe('button');
- });
-
- it('renders an icon with the open state', () => {
- expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('chevron-lg-down-icon');
- });
-
- it('renders collapsible lines content', () => {
- expect(wrapper.findAll('.js-line').length).toEqual(collapsibleSectionOpened.lines.length);
- });
- });
-
- it('emits onClickCollapsibleLine on click', async () => {
- createComponent({
- section: collapsibleSectionOpened,
- jobLogEndpoint,
- });
-
- findCollapsibleLine().trigger('click');
-
- await nextTick();
- expect(wrapper.emitted('onClickCollapsibleLine').length).toBe(1);
- });
-});
diff --git a/spec/frontend/jobs/components/log/duration_badge_spec.js b/spec/frontend/jobs/components/log/duration_badge_spec.js
deleted file mode 100644
index 644d05366a0..00000000000
--- a/spec/frontend/jobs/components/log/duration_badge_spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DurationBadge from '~/jobs/components/log/duration_badge.vue';
-
-describe('Job Log Duration Badge', () => {
- let wrapper;
-
- const data = {
- duration: '00:30:01',
- };
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(DurationBadge, {
- propsData: {
- ...props,
- },
- });
- };
-
- beforeEach(() => {
- createComponent(data);
- });
-
- it('renders provided duration', () => {
- expect(wrapper.text()).toBe(data.duration);
- });
-});
diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js
deleted file mode 100644
index c02d8c22655..00000000000
--- a/spec/frontend/jobs/components/log/line_header_spec.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import setWindowLocation from 'helpers/set_window_location_helper';
-import DurationBadge from '~/jobs/components/log/duration_badge.vue';
-import LineHeader from '~/jobs/components/log/line_header.vue';
-import LineNumber from '~/jobs/components/log/line_number.vue';
-
-describe('Job Log Header Line', () => {
- let wrapper;
-
- const data = {
- line: {
- content: [
- {
- text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
- style: 'term-fg-l-green',
- },
- ],
- lineNumber: 76,
- },
- isClosed: true,
- path: '/jashkenas/underscore/-/jobs/335',
- };
-
- const createComponent = (props = {}) => {
- wrapper = mount(LineHeader, {
- propsData: {
- ...props,
- },
- });
- };
-
- describe('line', () => {
- beforeEach(() => {
- createComponent(data);
- });
-
- it('renders the line number component', () => {
- expect(wrapper.findComponent(LineNumber).exists()).toBe(true);
- });
-
- it('renders a span the provided text', () => {
- expect(wrapper.find('span').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);
- });
- });
-
- describe('when isCloses is true', () => {
- beforeEach(() => {
- createComponent({ ...data, isClosed: true });
- });
-
- it('sets icon name to be chevron-lg-right', () => {
- expect(wrapper.vm.iconName).toEqual('chevron-lg-right');
- });
- });
-
- describe('when isCloses is false', () => {
- beforeEach(() => {
- createComponent({ ...data, isClosed: false });
- });
-
- it('sets icon name to be chevron-lg-down', () => {
- expect(wrapper.vm.iconName).toEqual('chevron-lg-down');
- });
- });
-
- describe('on click', () => {
- beforeEach(() => {
- createComponent(data);
- });
-
- it('emits toggleLine event', async () => {
- wrapper.trigger('click');
-
- await nextTick();
- expect(wrapper.emitted().toggleLine.length).toBe(1);
- });
- });
-
- describe('with duration', () => {
- beforeEach(() => {
- createComponent({ ...data, duration: '00:10' });
- });
-
- it('renders the duration badge', () => {
- expect(wrapper.findComponent(DurationBadge).exists()).toBe(true);
- });
- });
-
- describe('line highlighting', () => {
- describe('with hash', () => {
- beforeEach(() => {
- setWindowLocation(`http://foo.com/root/ci-project/-/jobs/6353#L77`);
-
- createComponent(data);
- });
-
- it('highlights line', () => {
- expect(wrapper.classes()).toContain('gl-bg-gray-700');
- });
- });
-
- describe('without hash', () => {
- beforeEach(() => {
- setWindowLocation(`http://foo.com/root/ci-project/-/jobs/6353`);
-
- createComponent(data);
- });
-
- it('does not highlight line', () => {
- expect(wrapper.classes()).not.toContain('gl-bg-gray-700');
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/log/line_number_spec.js b/spec/frontend/jobs/components/log/line_number_spec.js
deleted file mode 100644
index 4130c124a30..00000000000
--- a/spec/frontend/jobs/components/log/line_number_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import LineNumber from '~/jobs/components/log/line_number.vue';
-
-describe('Job Log Line Number', () => {
- let wrapper;
-
- const data = {
- lineNumber: 0,
- path: '/jashkenas/underscore/-/jobs/335',
- };
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(LineNumber, {
- propsData: {
- ...props,
- },
- });
- };
-
- beforeEach(() => {
- createComponent(data);
- });
-
- it('renders incremented lineNunber by 1', () => {
- expect(wrapper.text()).toBe('1');
- });
-
- it('renders link with lineNumber as an ID', () => {
- expect(wrapper.attributes().id).toBe('L1');
- });
-
- it('links to the provided path with line number as anchor', () => {
- expect(wrapper.attributes().href).toBe(`${data.path}#L1`);
- });
-});
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
deleted file mode 100644
index fad7a03beef..00000000000
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ /dev/null
@@ -1,267 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Line from '~/jobs/components/log/line.vue';
-import LineNumber from '~/jobs/components/log/line_number.vue';
-import setWindowLocation from 'helpers/set_window_location_helper';
-
-const httpUrl = 'http://example.com';
-const httpsUrl = 'https://example.com';
-const queryUrl = 'https://example.com?param=val';
-
-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;
- let data;
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(Line, {
- propsData: {
- ...props,
- },
- });
- };
-
- const findLine = () => wrapper.find('span');
- const findLink = () => findLine().find('a');
- const findLinks = () => findLine().findAll('a');
- const findLinkAttributeByIndex = (i) => findLinks().at(i).attributes();
-
- beforeEach(() => {
- data = mockProps();
- createComponent(data);
- });
-
- it('renders the line number component', () => {
- expect(wrapper.findComponent(LineNumber).exists()).toBe(true);
- });
-
- it('renders a span the provided text', () => {
- expect(findLine().text()).toBe(data.line.content[0].text);
- });
-
- it('renders the provided style as a class attribute', () => {
- expect(findLine().classes()).toContain(data.line.content[0].style);
- });
-
- describe('job urls as links', () => {
- 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 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('renders links with queries, surrounded by questions marks', () => {
- createComponent(mockProps({ text: `Did you see my url ${queryUrl}??` }));
-
- expect(findLine().text()).toBe('Did you see my url https://example.com?param=val??');
- expect(findLinkAttributeByIndex(0).href).toBe(queryUrl);
- });
-
- it('renders links with queries, surrounded by exclamation marks', () => {
- createComponent(mockProps({ text: `No! The ${queryUrl}!?` }));
-
- expect(findLine().text()).toBe('No! The https://example.com?param=val!?');
- expect(findLinkAttributeByIndex(0).href).toBe(queryUrl);
- });
-
- it('renders links that have brackets `[]` in their parameters', () => {
- const url = `${httpUrl}?label_name[]=frontend`;
-
- createComponent(mockProps({ text: url }));
-
- expect(findLine().text()).toBe(url);
- expect(findLinks().at(0).text()).toBe(url);
- expect(findLinks().at(0).attributes('href')).toBe(url);
- });
-
- it('renders multiple links surrounded by text', () => {
- createComponent(
- mockProps({ text: `Well, my HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl}` }),
- );
- expect(findLine().text()).toBe(
- 'Well, my HTTP url: http://example.com and my HTTPS url: https://example.com',
- );
-
- expect(findLinks()).toHaveLength(2);
-
- expect(findLinkAttributeByIndex(0).href).toBe(httpUrl);
- expect(findLinkAttributeByIndex(1).href).toBe(httpsUrl);
- });
-
- it('renders multiple links surrounded by text, with other symbols', () => {
- createComponent(
- mockProps({ text: `${httpUrl}, ${httpUrl}: ${httpsUrl}; ${httpsUrl}. ${httpsUrl}...` }),
- );
- expect(findLine().text()).toBe(
- 'http://example.com, http://example.com: https://example.com; https://example.com. https://example.com...',
- );
-
- expect(findLinks()).toHaveLength(5);
-
- expect(findLinkAttributeByIndex(0).href).toBe(httpUrl);
- expect(findLinkAttributeByIndex(1).href).toBe(httpUrl);
- expect(findLinkAttributeByIndex(2).href).toBe(httpsUrl);
- expect(findLinkAttributeByIndex(3).href).toBe(httpsUrl);
- expect(findLinkAttributeByIndex(4).href).toBe(httpsUrl);
- });
-
- it('renders multiple links surrounded by brackets', () => {
- createComponent(mockProps({ text: `(${httpUrl}) <${httpUrl}> {${httpsUrl}}` }));
- expect(findLine().text()).toBe(
- '(http://example.com) <http://example.com> {https://example.com}',
- );
-
- const links = findLinks();
-
- expect(links).toHaveLength(3);
-
- expect(links.at(0).text()).toBe(httpUrl);
- expect(links.at(0).attributes('href')).toBe(httpUrl);
-
- expect(links.at(1).text()).toBe(httpUrl);
- expect(links.at(1).attributes('href')).toBe(httpUrl);
-
- expect(links.at(2).text()).toBe(httpsUrl);
- expect(links.at(2).attributes('href')).toBe(httpsUrl);
- });
-
- it('renders text with symbols in it', () => {
- const text = 'apt-get update < /dev/null > /dev/null';
- createComponent(mockProps({ text }));
-
- expect(findLine().text()).toBe(text);
- });
-
- const jshref = 'javascript:doEvil();'; // eslint-disable-line no-script-url
-
- it.each`
- type | text
- ${'html link'} | ${'<a href="#">linked</a>'}
- ${'html script'} | ${'<script>doEvil();</script>'}
- ${'html strong'} | ${'<strong>highlighted</strong>'}
- ${'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);
- });
- });
-
- describe('job log search', () => {
- const mockSearchResults = [
- {
- offset: 1533,
- content: [{ text: '$ echo "82.71"', style: 'term-fg-l-green term-bold' }],
- section: 'step-script',
- lineNumber: 20,
- },
- { offset: 1560, content: [{ text: '82.71' }], section: 'step-script', lineNumber: 21 },
- ];
-
- it('applies highlight class to search result elements', () => {
- createComponent({
- line: {
- offset: 1560,
- content: [{ text: '82.71' }],
- section: 'step-script',
- lineNumber: 21,
- },
- path: '/root/ci-project/-/jobs/1089',
- searchResults: mockSearchResults,
- });
-
- expect(wrapper.classes()).toContain('gl-bg-gray-700');
- });
-
- it('does not apply highlight class to search result elements', () => {
- createComponent({
- line: {
- offset: 1560,
- content: [{ text: 'docker' }],
- section: 'step-script',
- lineNumber: 29,
- },
- path: '/root/ci-project/-/jobs/1089',
- searchResults: mockSearchResults,
- });
-
- expect(wrapper.classes()).not.toContain('gl-bg-gray-700');
- });
- });
-
- describe('job log hash highlighting', () => {
- describe('with hash', () => {
- beforeEach(() => {
- setWindowLocation(`http://foo.com/root/ci-project/-/jobs/6353#L77`);
- });
-
- it('applies highlight class to job log line', () => {
- createComponent({
- line: {
- offset: 24526,
- content: [{ text: 'job log content' }],
- section: 'custom-section',
- lineNumber: 76,
- },
- path: '/root/ci-project/-/jobs/6353',
- });
-
- expect(wrapper.classes()).toContain('gl-bg-gray-700');
- });
- });
-
- describe('without hash', () => {
- beforeEach(() => {
- setWindowLocation(`http://foo.com/root/ci-project/-/jobs/6353`);
- });
-
- it('does not apply highlight class to job log line', () => {
- createComponent({
- line: {
- offset: 24500,
- content: [{ text: 'line' }],
- section: 'custom-section',
- lineNumber: 10,
- },
- path: '/root/ci-project/-/jobs/6353',
- });
-
- expect(wrapper.classes()).not.toContain('gl-bg-gray-700');
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
deleted file mode 100644
index 9407b340950..00000000000
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import { mount } from '@vue/test-utils';
-import Vue from 'vue';
-// eslint-disable-next-line no-restricted-imports
-import Vuex from 'vuex';
-import waitForPromises from 'helpers/wait_for_promises';
-import { scrollToElement } from '~/lib/utils/common_utils';
-import Log from '~/jobs/components/log/log.vue';
-import LogLineHeader from '~/jobs/components/log/line_header.vue';
-import { logLinesParser } from '~/jobs/store/utils';
-import { jobLog } from './mock_data';
-
-jest.mock('~/lib/utils/common_utils', () => ({
- ...jest.requireActual('~/lib/utils/common_utils'),
- scrollToElement: jest.fn(),
-}));
-
-describe('Job Log', () => {
- let wrapper;
- let actions;
- let state;
- let store;
- let toggleCollapsibleLineMock;
-
- Vue.use(Vuex);
-
- const createComponent = () => {
- wrapper = mount(Log, {
- store,
- });
- };
-
- beforeEach(() => {
- toggleCollapsibleLineMock = jest.fn();
- actions = {
- toggleCollapsibleLine: toggleCollapsibleLineMock,
- };
-
- state = {
- jobLog: logLinesParser(jobLog),
- jobLogEndpoint: 'jobs/id',
- };
-
- store = new Vuex.Store({
- actions,
- state,
- });
- });
-
- const findCollapsibleLine = () => wrapper.findComponent(LogLineHeader);
-
- describe('line numbers', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders a line number for each open line', () => {
- expect(wrapper.find('#L1').text()).toBe('1');
- expect(wrapper.find('#L2').text()).toBe('2');
- expect(wrapper.find('#L3').text()).toBe('3');
- });
-
- it('links to the provided path and correct line number', () => {
- expect(wrapper.find('#L1').attributes('href')).toBe(`${state.jobLogEndpoint}#L1`);
- });
- });
-
- describe('collapsible sections', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders a clickable header section', () => {
- expect(findCollapsibleLine().attributes('role')).toBe('button');
- });
-
- it('renders an icon with the open state', () => {
- expect(findCollapsibleLine().find('[data-testid="chevron-lg-down-icon"]').exists()).toBe(
- true,
- );
- });
-
- describe('on click header section', () => {
- it('calls toggleCollapsibleLine', () => {
- findCollapsibleLine().trigger('click');
-
- expect(toggleCollapsibleLineMock).toHaveBeenCalled();
- });
- });
- });
-
- describe('anchor scrolling', () => {
- afterEach(() => {
- window.location.hash = '';
- });
-
- describe('when hash is not present', () => {
- it('does not scroll to line number', async () => {
- createComponent();
-
- await waitForPromises();
-
- expect(wrapper.find('#L6').exists()).toBe(false);
- expect(scrollToElement).not.toHaveBeenCalled();
- });
- });
-
- describe('when hash is present', () => {
- beforeEach(() => {
- window.location.hash = '#L6';
- });
-
- it('scrolls to line number', async () => {
- createComponent();
-
- state.jobLog = logLinesParser(jobLog, [], '#L6');
- await waitForPromises();
-
- expect(scrollToElement).toHaveBeenCalledTimes(1);
-
- state.jobLog = logLinesParser(jobLog, [], '#L7');
- await waitForPromises();
-
- expect(scrollToElement).toHaveBeenCalledTimes(1);
- });
-
- it('line number within collapsed section is visible', () => {
- state.jobLog = logLinesParser(jobLog, [], '#L6');
-
- createComponent();
-
- expect(wrapper.find('#L6').exists()).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/log/mock_data.js b/spec/frontend/jobs/components/log/mock_data.js
deleted file mode 100644
index fa51b92a044..00000000000
--- a/spec/frontend/jobs/components/log/mock_data.js
+++ /dev/null
@@ -1,218 +0,0 @@
-export const jobLog = [
- {
- offset: 1000,
- content: [{ text: 'Running with gitlab-runner 12.1.0 (de7731dd)' }],
- },
- {
- offset: 1001,
- content: [{ text: ' on docker-auto-scale-com 8a6210b8' }],
- },
- {
- offset: 1002,
- content: [
- {
- text: 'Using Docker executor with image dev.gitlab.org3',
- },
- ],
- section: 'prepare-executor',
- section_header: true,
- },
- {
- offset: 1003,
- content: [{ text: 'Starting service postgres:9.6.14 ...', style: 'text-green' }],
- section: 'prepare-executor',
- },
- {
- offset: 1004,
- content: [
- {
- text: 'Restore cache',
- style: 'term-fg-l-cyan term-bold',
- },
- ],
- section: 'restore-cache',
- section_header: true,
- section_options: {
- collapsed: 'true',
- },
- },
- {
- offset: 1005,
- content: [
- {
- text: 'Checking cache for ruby-gems-debian-bullseye-ruby-3.0-16...',
- style: 'term-fg-l-green term-bold',
- },
- ],
- section: 'restore-cache',
- },
-];
-
-export const utilsMockData = [
- {
- offset: 1001,
- content: [{ text: ' on docker-auto-scale-com 8a6210b8' }],
- },
- {
- offset: 1002,
- content: [
- {
- text:
- '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',
- section_header: true,
- },
- {
- offset: 1003,
- content: [{ text: 'Starting service postgres:9.6.14 ...' }],
- section: 'prepare-executor',
- },
- {
- offset: 1004,
- content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }],
- section: 'prepare-executor',
- },
- {
- offset: 1005,
- content: [],
- section: 'prepare-executor',
- section_duration: '10:00',
- },
-];
-
-export const originalTrace = [
- {
- offset: 1,
- content: [
- {
- text: 'Downloading',
- },
- ],
- },
-];
-
-export const regularIncremental = [
- {
- offset: 2,
- content: [
- {
- text: 'log line',
- },
- ],
- },
-];
-
-export const regularIncrementalRepeated = [
- {
- offset: 1,
- content: [
- {
- text: 'log line',
- },
- ],
- },
-];
-
-export const headerTrace = [
- {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'log line',
- },
- ],
- section: 'section',
- },
-];
-
-export const headerTraceIncremental = [
- {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- },
-];
-
-export const collapsibleTrace = [
- {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'log line',
- },
- ],
- section: 'section',
- },
- {
- offset: 2,
- content: [
- {
- text: 'log line',
- },
- ],
- section: 'section',
- },
-];
-
-export const collapsibleTraceIncremental = [
- {
- offset: 2,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- },
-];
-
-export const collapsibleSectionClosed = {
- offset: 5,
- section_header: true,
- isHeader: true,
- isClosed: true,
- line: {
- content: [{ text: 'foo' }],
- section: 'prepare-script',
- lineNumber: 1,
- },
- section_duration: '00:03',
- lines: [
- {
- offset: 80,
- content: [{ text: 'this is a collapsible nested section' }],
- section: 'prepare-script',
- lineNumber: 3,
- },
- ],
-};
-
-export const collapsibleSectionOpened = {
- offset: 5,
- section_header: true,
- isHeader: true,
- isClosed: false,
- line: {
- content: [{ text: 'foo' }],
- section: 'prepare-script',
- lineNumber: 1,
- },
- section_duration: '00:03',
- lines: [
- {
- offset: 80,
- content: [{ text: 'this is a collapsible nested section' }],
- section: 'prepare-script',
- lineNumber: 3,
- },
- ],
-};
diff --git a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
deleted file mode 100644
index f2d249b6014..00000000000
--- a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
+++ /dev/null
@@ -1,240 +0,0 @@
-import { GlModal } from '@gitlab/ui';
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
-import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
-import eventHub from '~/jobs/components/table/event_hub';
-import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
-import JobRetryMutation from '~/jobs/components/table/graphql/mutations/job_retry.mutation.graphql';
-import JobUnscheduleMutation from '~/jobs/components/table/graphql/mutations/job_unschedule.mutation.graphql';
-import JobCancelMutation from '~/jobs/components/table/graphql/mutations/job_cancel.mutation.graphql';
-import {
- mockJobsNodes,
- mockJobsNodesAsGuest,
- playMutationResponse,
- retryMutationResponse,
- unscheduleMutationResponse,
- cancelMutationResponse,
-} from '../../../mock_data';
-
-jest.mock('~/lib/utils/url_utility');
-
-Vue.use(VueApollo);
-
-describe('Job actions cell', () => {
- let wrapper;
-
- const findMockJob = (jobName, nodes = mockJobsNodes) => {
- const job = nodes.find(({ name }) => name === jobName);
- expect(job).toBeDefined(); // ensure job is present
- return job;
- };
-
- const mockJob = findMockJob('build');
- const cancelableJob = findMockJob('cancelable');
- const playableJob = findMockJob('playable');
- const retryableJob = findMockJob('retryable');
- const failedJob = findMockJob('failed');
- const scheduledJob = findMockJob('scheduled');
- const jobWithArtifact = findMockJob('with_artifact');
- const cannotPlayJob = findMockJob('playable', mockJobsNodesAsGuest);
- const cannotRetryJob = findMockJob('retryable', mockJobsNodesAsGuest);
- const cannotPlayScheduledJob = findMockJob('scheduled', mockJobsNodesAsGuest);
-
- const findRetryButton = () => wrapper.findByTestId('retry');
- const findPlayButton = () => wrapper.findByTestId('play');
- const findCancelButton = () => wrapper.findByTestId('cancel-button');
- const findDownloadArtifactsButton = () => wrapper.findByTestId('download-artifacts');
- const findCountdownButton = () => wrapper.findByTestId('countdown');
- const findPlayScheduledJobButton = () => wrapper.findByTestId('play-scheduled');
- const findUnscheduleButton = () => wrapper.findByTestId('unschedule');
-
- const findModal = () => wrapper.findComponent(GlModal);
-
- const playMutationHandler = jest.fn().mockResolvedValue(playMutationResponse);
- const retryMutationHandler = jest.fn().mockResolvedValue(retryMutationResponse);
- const unscheduleMutationHandler = jest.fn().mockResolvedValue(unscheduleMutationResponse);
- const cancelMutationHandler = jest.fn().mockResolvedValue(cancelMutationResponse);
-
- const $toast = {
- show: jest.fn(),
- };
-
- const createMockApolloProvider = (requestHandlers) => {
- return createMockApollo(requestHandlers);
- };
-
- const createComponent = (job, requestHandlers, props = {}) => {
- wrapper = shallowMountExtended(ActionsCell, {
- propsData: {
- job,
- ...props,
- },
- apolloProvider: createMockApolloProvider(requestHandlers),
- mocks: {
- $toast,
- },
- });
- };
-
- it('displays the artifacts download button with correct link', () => {
- createComponent(jobWithArtifact);
-
- expect(findDownloadArtifactsButton().attributes('href')).toBe(
- jobWithArtifact.artifacts.nodes[0].downloadPath,
- );
- });
-
- it('does not display an artifacts download button', () => {
- createComponent(mockJob);
-
- expect(findDownloadArtifactsButton().exists()).toBe(false);
- });
-
- it.each`
- button | action | jobType
- ${findPlayButton} | ${'play'} | ${cannotPlayJob}
- ${findRetryButton} | ${'retry'} | ${cannotRetryJob}
- ${findPlayScheduledJobButton} | ${'play scheduled'} | ${cannotPlayScheduledJob}
- `('does not display the $action button if user cannot update build', ({ button, jobType }) => {
- createComponent(jobType);
-
- expect(button().exists()).toBe(false);
- });
-
- it.each`
- button | action | jobType
- ${findPlayButton} | ${'play'} | ${playableJob}
- ${findRetryButton} | ${'retry'} | ${retryableJob}
- ${findDownloadArtifactsButton} | ${'download artifacts'} | ${jobWithArtifact}
- ${findCancelButton} | ${'cancel'} | ${cancelableJob}
- `('displays the $action button', ({ button, jobType }) => {
- createComponent(jobType);
-
- expect(button().exists()).toBe(true);
- });
-
- it.each`
- button | action | jobType | mutationFile | handler | jobId
- ${findPlayButton} | ${'play'} | ${playableJob} | ${JobPlayMutation} | ${playMutationHandler} | ${playableJob.id}
- ${findRetryButton} | ${'retry'} | ${retryableJob} | ${JobRetryMutation} | ${retryMutationHandler} | ${retryableJob.id}
- ${findCancelButton} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation} | ${cancelMutationHandler} | ${cancelableJob.id}
- `('performs the $action mutation', ({ button, jobType, mutationFile, handler, jobId }) => {
- createComponent(jobType, [[mutationFile, handler]]);
-
- button().vm.$emit('click');
-
- expect(handler).toHaveBeenCalledWith({ id: jobId });
- });
-
- it.each`
- button | action | jobType | mutationFile | handler
- ${findUnscheduleButton} | ${'unschedule'} | ${scheduledJob} | ${JobUnscheduleMutation} | ${unscheduleMutationHandler}
- ${findCancelButton} | ${'cancel'} | ${cancelableJob} | ${JobCancelMutation} | ${cancelMutationHandler}
- `(
- 'the mutation action $action emits the jobActionPerformed event',
- async ({ button, jobType, mutationFile, handler }) => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- createComponent(jobType, [[mutationFile, handler]]);
-
- button().vm.$emit('click');
-
- await waitForPromises();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('jobActionPerformed');
- expect(redirectTo).not.toHaveBeenCalled(); // eslint-disable-line import/no-deprecated
- },
- );
-
- it.each`
- button | action | jobType | mutationFile | handler | redirectLink
- ${findPlayButton} | ${'play'} | ${playableJob} | ${JobPlayMutation} | ${playMutationHandler} | ${'/root/project/-/jobs/1986'}
- ${findRetryButton} | ${'retry'} | ${retryableJob} | ${JobRetryMutation} | ${retryMutationHandler} | ${'/root/project/-/jobs/1985'}
- `(
- 'the mutation action $action redirects to the job',
- async ({ button, jobType, mutationFile, handler, redirectLink }) => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- createComponent(jobType, [[mutationFile, handler]]);
-
- button().vm.$emit('click');
-
- await waitForPromises();
-
- expect(redirectTo).toHaveBeenCalledWith(redirectLink); // eslint-disable-line import/no-deprecated
- expect(eventHub.$emit).not.toHaveBeenCalled();
- },
- );
-
- it.each`
- button | action | jobType
- ${findPlayButton} | ${'play'} | ${playableJob}
- ${findRetryButton} | ${'retry'} | ${retryableJob}
- ${findCancelButton} | ${'cancel'} | ${cancelableJob}
- ${findUnscheduleButton} | ${'unschedule'} | ${scheduledJob}
- `('disables the $action button after first request', async ({ button, jobType }) => {
- createComponent(jobType);
-
- expect(button().props('disabled')).toBe(false);
-
- button().vm.$emit('click');
-
- await waitForPromises();
-
- expect(button().props('disabled')).toBe(true);
- });
-
- describe('Retry button title', () => {
- it('displays retry title when job has failed and is retryable', () => {
- createComponent(failedJob);
-
- expect(findRetryButton().attributes('title')).toBe('Retry');
- });
-
- it('displays run again title when job has passed and is retryable', () => {
- createComponent(retryableJob);
-
- expect(findRetryButton().attributes('title')).toBe('Run again');
- });
- });
-
- describe('Scheduled Jobs', () => {
- const today = () => new Date('2021-08-31');
-
- beforeEach(() => {
- jest.spyOn(Date, 'now').mockImplementation(today);
- });
-
- it('displays the countdown, play and unschedule buttons', () => {
- createComponent(scheduledJob);
-
- expect(findCountdownButton().exists()).toBe(true);
- expect(findPlayScheduledJobButton().exists()).toBe(true);
- expect(findUnscheduleButton().exists()).toBe(true);
- });
-
- it('unschedules a job', () => {
- createComponent(scheduledJob, [[JobUnscheduleMutation, unscheduleMutationHandler]]);
-
- findUnscheduleButton().vm.$emit('click');
-
- expect(unscheduleMutationHandler).toHaveBeenCalledWith({
- id: scheduledJob.id,
- });
- });
-
- it('shows the play job confirmation modal', async () => {
- createComponent(scheduledJob);
-
- findPlayScheduledJobButton().vm.$emit('click');
-
- await nextTick();
-
- expect(findModal().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/cells/duration_cell_spec.js b/spec/frontend/jobs/components/table/cells/duration_cell_spec.js
deleted file mode 100644
index d015edb0e91..00000000000
--- a/spec/frontend/jobs/components/table/cells/duration_cell_spec.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import DurationCell from '~/jobs/components/table/cells/duration_cell.vue';
-
-describe('Duration Cell', () => {
- let wrapper;
-
- const findJobDuration = () => wrapper.findByTestId('job-duration');
- const findJobFinishedTime = () => wrapper.findByTestId('job-finished-time');
- const findDurationIcon = () => wrapper.findByTestId('duration-icon');
- const findFinishedTimeIcon = () => wrapper.findByTestId('finished-time-icon');
-
- const createComponent = (props) => {
- wrapper = extendedWrapper(
- shallowMount(DurationCell, {
- propsData: {
- job: {
- ...props,
- },
- },
- }),
- );
- };
-
- it('does not display duration or finished time when no properties are present', () => {
- createComponent();
-
- expect(findJobDuration().exists()).toBe(false);
- expect(findJobFinishedTime().exists()).toBe(false);
- });
-
- it('displays duration and finished time when both properties are present', () => {
- const props = {
- duration: 7,
- finishedAt: '2021-04-26T13:37:52Z',
- };
-
- createComponent(props);
-
- expect(findJobDuration().exists()).toBe(true);
- expect(findJobFinishedTime().exists()).toBe(true);
- });
-
- it('displays only the duration of the job when the duration property is present', () => {
- const props = {
- duration: 7,
- };
-
- createComponent(props);
-
- expect(findJobDuration().exists()).toBe(true);
- expect(findJobFinishedTime().exists()).toBe(false);
- });
-
- it('displays only the finished time of the job when the finshedAt property is present', () => {
- const props = {
- finishedAt: '2021-04-26T13:37:52Z',
- };
-
- createComponent(props);
-
- expect(findJobFinishedTime().exists()).toBe(true);
- expect(findJobDuration().exists()).toBe(false);
- });
-
- it('displays icons for finished time and duration', () => {
- const props = {
- duration: 7,
- finishedAt: '2021-04-26T13:37:52Z',
- };
-
- createComponent(props);
-
- expect(findFinishedTimeIcon().props('name')).toBe('calendar');
- expect(findDurationIcon().props('name')).toBe('timer');
- });
-});
diff --git a/spec/frontend/jobs/components/table/cells/job_cell_spec.js b/spec/frontend/jobs/components/table/cells/job_cell_spec.js
deleted file mode 100644
index 73e37eed5f1..00000000000
--- a/spec/frontend/jobs/components/table/cells/job_cell_spec.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import JobCell from '~/jobs/components/table/cells/job_cell.vue';
-import { mockJobsNodes, mockJobsNodesAsGuest } from '../../../mock_data';
-
-describe('Job Cell', () => {
- let wrapper;
-
- const findMockJob = (jobName, nodes = mockJobsNodes) => {
- const job = nodes.find(({ name }) => name === jobName);
- expect(job).toBeDefined(); // ensure job is present
- return job;
- };
-
- const mockJob = findMockJob('build');
- const jobCreatedByTag = findMockJob('created_by_tag');
- const pendingJob = findMockJob('pending');
- const jobAsGuest = findMockJob('build', mockJobsNodesAsGuest);
-
- const findJobIdLink = () => wrapper.findByTestId('job-id-link');
- const findJobIdNoLink = () => wrapper.findByTestId('job-id-limited-access');
- const findJobRef = () => wrapper.findByTestId('job-ref');
- const findJobSha = () => wrapper.findByTestId('job-sha');
- const findLabelIcon = () => wrapper.findByTestId('label-icon');
- const findForkIcon = () => wrapper.findByTestId('fork-icon');
- const findStuckIcon = () => wrapper.findByTestId('stuck-icon');
- const findAllTagBadges = () => wrapper.findAllByTestId('job-tag-badge');
-
- const findBadgeById = (id) => wrapper.findByTestId(id);
-
- const createComponent = (job = mockJob) => {
- wrapper = extendedWrapper(
- shallowMount(JobCell, {
- propsData: {
- job,
- },
- }),
- );
- };
-
- describe('Job Id', () => {
- it('displays the job id and links to the job', () => {
- createComponent();
-
- const expectedJobId = `#${getIdFromGraphQLId(mockJob.id)}`;
-
- expect(findJobIdLink().text()).toBe(expectedJobId);
- expect(findJobIdLink().attributes('href')).toBe(mockJob.detailedStatus.detailsPath);
- expect(findJobIdNoLink().exists()).toBe(false);
- });
-
- it('display the job id with no link', () => {
- createComponent(jobAsGuest);
-
- const expectedJobId = `#${getIdFromGraphQLId(jobAsGuest.id)}`;
-
- expect(findJobIdNoLink().text()).toBe(expectedJobId);
- expect(findJobIdNoLink().exists()).toBe(true);
- expect(findJobIdLink().exists()).toBe(false);
- });
- });
-
- describe('Ref of the job', () => {
- it('displays the ref name and links to the ref', () => {
- createComponent();
-
- expect(findJobRef().text()).toBe(mockJob.refName);
- expect(findJobRef().attributes('href')).toBe(mockJob.refPath);
- });
-
- it('displays fork icon when job is not created by tag', () => {
- createComponent();
-
- expect(findForkIcon().exists()).toBe(true);
- expect(findLabelIcon().exists()).toBe(false);
- });
-
- it('displays label icon when job is created by a tag', () => {
- createComponent(jobCreatedByTag);
-
- expect(findLabelIcon().exists()).toBe(true);
- expect(findForkIcon().exists()).toBe(false);
- });
- });
-
- describe('Commit of the job', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('displays the sha and links to the commit', () => {
- expect(findJobSha().text()).toBe(mockJob.shortSha);
- expect(findJobSha().attributes('href')).toBe(mockJob.commitPath);
- });
- });
-
- describe('Job badges', () => {
- it('displays tags of the job', () => {
- const mockJobWithTags = {
- tags: ['tag-1', 'tag-2', 'tag-3'],
- };
-
- createComponent(mockJobWithTags);
-
- expect(findAllTagBadges()).toHaveLength(mockJobWithTags.tags.length);
- });
-
- it.each`
- testId | text
- ${'manual-job-badge'} | ${'manual'}
- ${'triggered-job-badge'} | ${'triggered'}
- ${'fail-job-badge'} | ${'allowed to fail'}
- ${'delayed-job-badge'} | ${'delayed'}
- `('displays the static $text badge', ({ testId, text }) => {
- createComponent({
- manualJob: true,
- triggered: true,
- allowFailure: true,
- scheduledAt: '2021-03-09T14:58:50+00:00',
- });
-
- expect(findBadgeById(testId).exists()).toBe(true);
- expect(findBadgeById(testId).text()).toBe(text);
- });
- });
-
- describe('Job icons', () => {
- it('stuck icon is not shown if job is not stuck', () => {
- createComponent();
-
- expect(findStuckIcon().exists()).toBe(false);
- });
-
- it('stuck icon is shown if job is pending', () => {
- createComponent(pendingJob);
-
- expect(findStuckIcon().exists()).toBe(true);
- expect(findStuckIcon().attributes('name')).toBe('warning');
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/cells/pipeline_cell_spec.js b/spec/frontend/jobs/components/table/cells/pipeline_cell_spec.js
deleted file mode 100644
index 3d424b20964..00000000000
--- a/spec/frontend/jobs/components/table/cells/pipeline_cell_spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import { GlAvatar } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import PipelineCell from '~/jobs/components/table/cells/pipeline_cell.vue';
-
-const mockJobWithoutUser = {
- id: 'gid://gitlab/Ci::Build/2264',
- pipeline: {
- id: 'gid://gitlab/Ci::Pipeline/460',
- path: '/root/ci-project/-/pipelines/460',
- },
-};
-
-const mockJobWithUser = {
- id: 'gid://gitlab/Ci::Build/2264',
- pipeline: {
- id: 'gid://gitlab/Ci::Pipeline/460',
- path: '/root/ci-project/-/pipelines/460',
- user: {
- avatarUrl:
- 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- webPath: '/root',
- },
- },
-};
-
-describe('Pipeline Cell', () => {
- let wrapper;
-
- const findPipelineId = () => wrapper.findByTestId('pipeline-id');
- const findPipelineUserLink = () => wrapper.findByTestId('pipeline-user-link');
- const findUserAvatar = () => wrapper.findComponent(GlAvatar);
-
- const createComponent = (props = mockJobWithUser) => {
- wrapper = extendedWrapper(
- shallowMount(PipelineCell, {
- propsData: {
- job: props,
- },
- }),
- );
- };
-
- describe('Pipeline Id', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('displays the pipeline id and links to the pipeline', () => {
- const expectedPipelineId = `#${getIdFromGraphQLId(mockJobWithUser.pipeline.id)}`;
-
- expect(findPipelineId().text()).toBe(expectedPipelineId);
- expect(findPipelineId().attributes('href')).toBe(mockJobWithUser.pipeline.path);
- });
- });
-
- describe('Pipeline created by', () => {
- const apiWrapperText = 'API';
-
- it('shows and links to the pipeline user', () => {
- createComponent();
-
- expect(findPipelineUserLink().exists()).toBe(true);
- expect(findPipelineUserLink().attributes('href')).toBe(mockJobWithUser.pipeline.user.webPath);
- expect(findUserAvatar().attributes('src')).toBe(mockJobWithUser.pipeline.user.avatarUrl);
- expect(wrapper.text()).not.toContain(apiWrapperText);
- });
-
- it('shows pipeline was created by the API', () => {
- createComponent(mockJobWithoutUser);
-
- expect(findPipelineUserLink().exists()).toBe(false);
- expect(findUserAvatar().exists()).toBe(false);
- expect(wrapper.text()).toContain(apiWrapperText);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/graphql/cache_config_spec.js b/spec/frontend/jobs/components/table/graphql/cache_config_spec.js
deleted file mode 100644
index e3b1ca1cce3..00000000000
--- a/spec/frontend/jobs/components/table/graphql/cache_config_spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import cacheConfig from '~/jobs/components/table/graphql/cache_config';
-import {
- CIJobConnectionExistingCache,
- CIJobConnectionIncomingCache,
- CIJobConnectionIncomingCacheRunningStatus,
-} from '../../../mock_data';
-
-const firstLoadArgs = { first: 3, statuses: 'PENDING' };
-const runningArgs = { first: 3, statuses: 'RUNNING' };
-
-describe('jobs/components/table/graphql/cache_config', () => {
- describe('when fetching data with the same statuses', () => {
- it('should contain cache nodes and a status when merging caches on first load', () => {
- const res = cacheConfig.typePolicies.CiJobConnection.merge({}, CIJobConnectionIncomingCache, {
- args: firstLoadArgs,
- });
-
- expect(res.nodes).toHaveLength(CIJobConnectionIncomingCache.nodes.length);
- expect(res.statuses).toBe('PENDING');
- });
-
- it('should add to existing caches when merging caches after first load', () => {
- const res = cacheConfig.typePolicies.CiJobConnection.merge(
- CIJobConnectionExistingCache,
- CIJobConnectionIncomingCache,
- {
- args: firstLoadArgs,
- },
- );
-
- expect(res.nodes).toHaveLength(
- CIJobConnectionIncomingCache.nodes.length + CIJobConnectionExistingCache.nodes.length,
- );
- });
-
- it('should not add to existing cache if the incoming elements are the same', () => {
- // simulate that this is the last page
- const finalExistingCache = {
- ...CIJobConnectionExistingCache,
- pageInfo: {
- hasNextPage: false,
- },
- };
-
- const res = cacheConfig.typePolicies.CiJobConnection.merge(
- CIJobConnectionExistingCache,
- finalExistingCache,
- {
- args: firstLoadArgs,
- },
- );
-
- expect(res.nodes).toHaveLength(CIJobConnectionExistingCache.nodes.length);
- });
-
- it('should contain the pageInfo key as part of the result', () => {
- const res = cacheConfig.typePolicies.CiJobConnection.merge({}, CIJobConnectionIncomingCache, {
- args: firstLoadArgs,
- });
-
- expect(res.pageInfo).toEqual(
- expect.objectContaining({
- __typename: 'PageInfo',
- endCursor: 'eyJpZCI6IjIwNTEifQ',
- hasNextPage: true,
- hasPreviousPage: false,
- startCursor: 'eyJpZCI6IjIxNzMifQ',
- }),
- );
- });
- });
-
- describe('when fetching data with different statuses', () => {
- it('should reset cache when a cache already exists', () => {
- const res = cacheConfig.typePolicies.CiJobConnection.merge(
- CIJobConnectionExistingCache,
- CIJobConnectionIncomingCacheRunningStatus,
- {
- args: runningArgs,
- },
- );
-
- expect(res.nodes).not.toEqual(CIJobConnectionExistingCache.nodes);
- expect(res.nodes).toHaveLength(CIJobConnectionIncomingCacheRunningStatus.nodes.length);
- });
- });
-
- describe('when incoming data has no nodes', () => {
- it('should return existing cache', () => {
- const res = cacheConfig.typePolicies.CiJobConnection.merge(
- CIJobConnectionExistingCache,
- { __typename: 'CiJobConnection', count: 500 },
- {
- args: { statuses: 'SUCCESS' },
- },
- );
-
- const expectedResponse = {
- ...CIJobConnectionExistingCache,
- statuses: 'SUCCESS',
- };
-
- expect(res).toEqual(expectedResponse);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/job_table_app_spec.js b/spec/frontend/jobs/components/table/job_table_app_spec.js
deleted file mode 100644
index 032b83ca22b..00000000000
--- a/spec/frontend/jobs/components/table/job_table_app_spec.js
+++ /dev/null
@@ -1,338 +0,0 @@
-import { GlAlert, GlEmptyState, GlIntersectionObserver, GlLoadingIcon } from '@gitlab/ui';
-import { mount, shallowMount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import { s__ } from '~/locale';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { TEST_HOST } from 'spec/test_constants';
-import { createAlert } from '~/alert';
-import getJobsQuery from '~/jobs/components/table/graphql/queries/get_jobs.query.graphql';
-import getJobsCountQuery from '~/jobs/components/table/graphql/queries/get_jobs_count.query.graphql';
-import JobsTable from '~/jobs/components/table/jobs_table.vue';
-import JobsTableApp from '~/jobs/components/table/jobs_table_app.vue';
-import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue';
-import JobsFilteredSearch from '~/jobs/components/filtered_search/jobs_filtered_search.vue';
-import JobsSkeletonLoader from '~/pages/admin/jobs/components/jobs_skeleton_loader.vue';
-import * as urlUtils from '~/lib/utils/url_utility';
-import {
- mockJobsResponsePaginated,
- mockJobsResponseEmpty,
- mockFailedSearchToken,
- mockJobsCountResponse,
-} from '../../mock_data';
-
-const projectPath = 'gitlab-org/gitlab';
-Vue.use(VueApollo);
-
-jest.mock('~/alert');
-
-describe('Job table app', () => {
- let wrapper;
-
- const successHandler = jest.fn().mockResolvedValue(mockJobsResponsePaginated);
- const failedHandler = jest.fn().mockRejectedValue(new Error('GraphQL error'));
- const emptyHandler = jest.fn().mockResolvedValue(mockJobsResponseEmpty);
-
- const countSuccessHandler = jest.fn().mockResolvedValue(mockJobsCountResponse);
-
- const findSkeletonLoader = () => wrapper.findComponent(JobsSkeletonLoader);
- const findLoadingSpinner = () => wrapper.findComponent(GlLoadingIcon);
- const findTable = () => wrapper.findComponent(JobsTable);
- const findTabs = () => wrapper.findComponent(JobsTableTabs);
- const findAlert = () => wrapper.findComponent(GlAlert);
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findFilteredSearch = () => wrapper.findComponent(JobsFilteredSearch);
-
- const triggerInfiniteScroll = () =>
- wrapper.findComponent(GlIntersectionObserver).vm.$emit('appear');
-
- const createMockApolloProvider = (handler, countHandler) => {
- const requestHandlers = [
- [getJobsQuery, handler],
- [getJobsCountQuery, countHandler],
- ];
-
- return createMockApollo(requestHandlers);
- };
-
- const createComponent = ({
- handler = successHandler,
- countHandler = countSuccessHandler,
- mountFn = shallowMount,
- } = {}) => {
- wrapper = mountFn(JobsTableApp, {
- provide: {
- fullPath: projectPath,
- },
- apolloProvider: createMockApolloProvider(handler, countHandler),
- });
- };
-
- describe('loading state', () => {
- it('should display skeleton loader when loading', () => {
- createComponent();
-
- expect(findSkeletonLoader().exists()).toBe(true);
- expect(findTable().exists()).toBe(false);
- expect(findLoadingSpinner().exists()).toBe(false);
- });
-
- it('when switching tabs only the skeleton loader should show', () => {
- createComponent();
-
- findTabs().vm.$emit('fetchJobsByStatus', null);
-
- expect(findSkeletonLoader().exists()).toBe(true);
- expect(findLoadingSpinner().exists()).toBe(false);
- });
- });
-
- describe('loaded state', () => {
- beforeEach(async () => {
- createComponent();
-
- await waitForPromises();
- });
-
- it('should display the jobs table with data', () => {
- expect(findTable().exists()).toBe(true);
- expect(findSkeletonLoader().exists()).toBe(false);
- expect(findLoadingSpinner().exists()).toBe(false);
- });
-
- it('should refetch jobs query on fetchJobsByStatus event', async () => {
- expect(successHandler).toHaveBeenCalledTimes(1);
-
- await findTabs().vm.$emit('fetchJobsByStatus');
-
- expect(successHandler).toHaveBeenCalledTimes(2);
- });
-
- it('avoids refetch jobs query when scope has not changed', async () => {
- expect(successHandler).toHaveBeenCalledTimes(1);
-
- await findTabs().vm.$emit('fetchJobsByStatus', null);
-
- expect(successHandler).toHaveBeenCalledTimes(1);
- });
-
- it('should refetch jobs count query when the amount jobs and count do not match', async () => {
- expect(countSuccessHandler).toHaveBeenCalledTimes(1);
-
- // after applying filter a new count is fetched
- findFilteredSearch().vm.$emit('filterJobsBySearch', [mockFailedSearchToken]);
-
- expect(countSuccessHandler).toHaveBeenCalledTimes(2);
-
- // tab is switched to `finished`, no count
- await findTabs().vm.$emit('fetchJobsByStatus', ['FAILED', 'SUCCESS', 'CANCELED']);
-
- // tab is switched back to `all`, the old filter count has to be overwritten with new count
- await findTabs().vm.$emit('fetchJobsByStatus', null);
-
- expect(countSuccessHandler).toHaveBeenCalledTimes(3);
- });
-
- describe('when infinite scrolling is triggered', () => {
- it('does not display a skeleton loader', () => {
- triggerInfiniteScroll();
-
- expect(findSkeletonLoader().exists()).toBe(false);
- });
-
- it('handles infinite scrolling by calling fetch more', async () => {
- triggerInfiniteScroll();
-
- await nextTick();
-
- const pageSize = 30;
-
- expect(findLoadingSpinner().exists()).toBe(true);
-
- await waitForPromises();
-
- expect(findLoadingSpinner().exists()).toBe(false);
-
- expect(successHandler).toHaveBeenLastCalledWith({
- first: pageSize,
- fullPath: projectPath,
- after: mockJobsResponsePaginated.data.project.jobs.pageInfo.endCursor,
- });
- });
- });
- });
-
- describe('error state', () => {
- it('should show an alert if there is an error fetching the jobs data', async () => {
- createComponent({ handler: failedHandler });
-
- await waitForPromises();
-
- expect(findAlert().text()).toBe('There was an error fetching the jobs for your project.');
- expect(findTable().exists()).toBe(false);
- });
-
- it('should show an alert if there is an error fetching the jobs count data', async () => {
- createComponent({ handler: successHandler, countHandler: failedHandler });
-
- await waitForPromises();
-
- expect(findAlert().text()).toBe(
- 'There was an error fetching the number of jobs for your project.',
- );
- });
-
- it('jobs table should still load if count query fails', async () => {
- createComponent({ handler: successHandler, countHandler: failedHandler });
-
- await waitForPromises();
-
- expect(findTable().exists()).toBe(true);
- });
-
- it('jobs count should be zero if count query fails', async () => {
- createComponent({ handler: successHandler, countHandler: failedHandler });
-
- await waitForPromises();
-
- expect(findTabs().props('allJobsCount')).toBe(0);
- });
- });
-
- describe('empty state', () => {
- it('should display empty state if there are no jobs and tab scope is null', async () => {
- createComponent({ handler: emptyHandler, mountFn: mount });
-
- await waitForPromises();
-
- expect(findEmptyState().exists()).toBe(true);
- expect(findTable().exists()).toBe(false);
- });
-
- it('should not display empty state if there are jobs and tab scope is not null', async () => {
- createComponent({ handler: successHandler, mountFn: mount });
-
- await waitForPromises();
-
- expect(findEmptyState().exists()).toBe(false);
- expect(findTable().exists()).toBe(true);
- });
- });
-
- describe('filtered search', () => {
- it('should display filtered search', () => {
- createComponent();
-
- expect(findFilteredSearch().exists()).toBe(true);
- });
-
- // this test should be updated once BE supports tab and filtered search filtering
- // https://gitlab.com/gitlab-org/gitlab/-/issues/356210
- it.each`
- scope | shouldDisplay
- ${null} | ${true}
- ${['FAILED', 'SUCCESS', 'CANCELED']} | ${false}
- `(
- 'with tab scope $scope the filtered search displays $shouldDisplay',
- async ({ scope, shouldDisplay }) => {
- createComponent();
-
- await waitForPromises();
-
- await findTabs().vm.$emit('fetchJobsByStatus', scope);
-
- expect(findFilteredSearch().exists()).toBe(shouldDisplay);
- },
- );
-
- it('refetches jobs query when filtering', async () => {
- createComponent();
-
- expect(successHandler).toHaveBeenCalledTimes(1);
-
- await findFilteredSearch().vm.$emit('filterJobsBySearch', [mockFailedSearchToken]);
-
- expect(successHandler).toHaveBeenCalledTimes(2);
- });
-
- it('refetches jobs count query when filtering', async () => {
- createComponent();
-
- expect(countSuccessHandler).toHaveBeenCalledTimes(1);
-
- await findFilteredSearch().vm.$emit('filterJobsBySearch', [mockFailedSearchToken]);
-
- expect(countSuccessHandler).toHaveBeenCalledTimes(2);
- });
-
- it('shows raw text warning when user inputs raw text', async () => {
- const expectedWarning = {
- message: s__(
- 'Jobs|Raw text search is not currently supported for the jobs filtered search feature. Please use the available search tokens.',
- ),
- type: 'warning',
- };
-
- createComponent();
-
- expect(successHandler).toHaveBeenCalledTimes(1);
- expect(countSuccessHandler).toHaveBeenCalledTimes(1);
-
- await findFilteredSearch().vm.$emit('filterJobsBySearch', ['raw text']);
-
- expect(createAlert).toHaveBeenCalledWith(expectedWarning);
- expect(successHandler).toHaveBeenCalledTimes(1);
- expect(countSuccessHandler).toHaveBeenCalledTimes(1);
- });
-
- it('updates URL query string when filtering jobs by status', async () => {
- createComponent();
-
- jest.spyOn(urlUtils, 'updateHistory');
-
- await findFilteredSearch().vm.$emit('filterJobsBySearch', [mockFailedSearchToken]);
-
- expect(urlUtils.updateHistory).toHaveBeenCalledWith({
- url: `${TEST_HOST}/?statuses=FAILED`,
- });
- });
-
- it('resets query param after clearing tokens', () => {
- createComponent();
-
- jest.spyOn(urlUtils, 'updateHistory');
-
- findFilteredSearch().vm.$emit('filterJobsBySearch', [mockFailedSearchToken]);
-
- expect(successHandler).toHaveBeenCalledWith({
- first: 30,
- fullPath: 'gitlab-org/gitlab',
- statuses: 'FAILED',
- });
- expect(countSuccessHandler).toHaveBeenCalledWith({
- fullPath: 'gitlab-org/gitlab',
- statuses: 'FAILED',
- });
- expect(urlUtils.updateHistory).toHaveBeenCalledWith({
- url: `${TEST_HOST}/?statuses=FAILED`,
- });
-
- findFilteredSearch().vm.$emit('filterJobsBySearch', []);
-
- expect(urlUtils.updateHistory).toHaveBeenCalledWith({
- url: `${TEST_HOST}/`,
- });
-
- expect(successHandler).toHaveBeenCalledWith({
- first: 30,
- fullPath: 'gitlab-org/gitlab',
- statuses: null,
- });
- expect(countSuccessHandler).toHaveBeenCalledWith({
- fullPath: 'gitlab-org/gitlab',
- statuses: null,
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/jobs_table_empty_state_spec.js b/spec/frontend/jobs/components/table/jobs_table_empty_state_spec.js
deleted file mode 100644
index 05b066a9edc..00000000000
--- a/spec/frontend/jobs/components/table/jobs_table_empty_state_spec.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { GlEmptyState } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import JobsTableEmptyState from '~/jobs/components/table/jobs_table_empty_state.vue';
-
-describe('Jobs table empty state', () => {
- let wrapper;
-
- const pipelineEditorPath = '/root/project/-/ci/editor';
- const emptyStateSvgPath = 'assets/jobs-empty-state.svg';
-
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
-
- const createComponent = () => {
- wrapper = shallowMount(JobsTableEmptyState, {
- provide: {
- pipelineEditorPath,
- emptyStateSvgPath,
- },
- });
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- it('displays empty state', () => {
- expect(findEmptyState().exists()).toBe(true);
- });
-
- it('links to the pipeline editor', () => {
- expect(findEmptyState().props('primaryButtonLink')).toBe(pipelineEditorPath);
- });
-
- it('shows an empty state image', () => {
- expect(findEmptyState().props('svgPath')).toBe(emptyStateSvgPath);
- });
-});
diff --git a/spec/frontend/jobs/components/table/jobs_table_spec.js b/spec/frontend/jobs/components/table/jobs_table_spec.js
deleted file mode 100644
index 654b6d1c130..00000000000
--- a/spec/frontend/jobs/components/table/jobs_table_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { GlTable } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import JobsTable from '~/jobs/components/table/jobs_table.vue';
-import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
-import { DEFAULT_FIELDS_ADMIN } from '~/pages/admin/jobs/components/constants';
-import ProjectCell from '~/pages/admin/jobs/components/table/cell/project_cell.vue';
-import RunnerCell from '~/pages/admin/jobs/components/table/cells/runner_cell.vue';
-import { mockJobsNodes, mockAllJobsNodes } from '../../mock_data';
-
-describe('Jobs Table', () => {
- let wrapper;
-
- const findTable = () => wrapper.findComponent(GlTable);
- const findCiBadgeLink = () => wrapper.findComponent(CiBadgeLink);
- const findTableRows = () => wrapper.findAllByTestId('jobs-table-row');
- const findJobStage = () => wrapper.findByTestId('job-stage-name');
- const findJobName = () => wrapper.findByTestId('job-name');
- const findJobProject = () => wrapper.findComponent(ProjectCell);
- const findJobRunner = () => wrapper.findComponent(RunnerCell);
- const findAllCoverageJobs = () => wrapper.findAllByTestId('job-coverage');
-
- const createComponent = (props = {}) => {
- wrapper = extendedWrapper(
- mount(JobsTable, {
- propsData: {
- ...props,
- },
- }),
- );
- };
-
- describe('jobs table', () => {
- beforeEach(() => {
- createComponent({ jobs: mockJobsNodes });
- });
-
- it('displays the jobs table', () => {
- expect(findTable().exists()).toBe(true);
- });
-
- it('displays correct number of job rows', () => {
- expect(findTableRows()).toHaveLength(mockJobsNodes.length);
- });
-
- it('displays job status', () => {
- expect(findCiBadgeLink().exists()).toBe(true);
- });
-
- it('displays the job stage and name', () => {
- const [firstJob] = mockJobsNodes;
-
- expect(findJobStage().text()).toBe(firstJob.stage.name);
- expect(findJobName().text()).toBe(firstJob.name);
- });
-
- it('displays the coverage for only jobs that have coverage', () => {
- const jobsThatHaveCoverage = mockJobsNodes.filter((job) => job.coverage !== null);
-
- jobsThatHaveCoverage.forEach((job, index) => {
- expect(findAllCoverageJobs().at(index).text()).toBe(`${job.coverage}%`);
- });
- expect(findAllCoverageJobs()).toHaveLength(jobsThatHaveCoverage.length);
- });
- });
-
- describe('regular user', () => {
- beforeEach(() => {
- createComponent({ jobs: mockJobsNodes });
- });
-
- it('hides the job runner', () => {
- expect(findJobRunner().exists()).toBe(false);
- });
-
- it('hides the job project link', () => {
- expect(findJobProject().exists()).toBe(false);
- });
- });
-
- describe('admin mode', () => {
- beforeEach(() => {
- createComponent({ jobs: mockAllJobsNodes, tableFields: DEFAULT_FIELDS_ADMIN, admin: true });
- });
-
- it('displays the runner cell', () => {
- expect(findJobRunner().exists()).toBe(true);
- });
-
- it('displays the project cell', () => {
- expect(findJobProject().exists()).toBe(true);
- });
-
- it('displays correct number of job rows', () => {
- expect(findTableRows()).toHaveLength(mockAllJobsNodes.length);
- });
- });
-});
diff --git a/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js b/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js
deleted file mode 100644
index d20a732508a..00000000000
--- a/spec/frontend/jobs/components/table/jobs_table_tabs_spec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import { GlTab } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { trimText } from 'helpers/text_helper';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import JobsTableTabs from '~/jobs/components/table/jobs_table_tabs.vue';
-import CancelJobs from '~/pages/admin/jobs/components/cancel_jobs.vue';
-
-describe('Jobs Table Tabs', () => {
- let wrapper;
-
- const defaultProps = {
- allJobsCount: 286,
- loading: false,
- };
-
- const adminProps = {
- ...defaultProps,
- showCancelAllJobsButton: true,
- };
-
- const statuses = {
- success: 'SUCCESS',
- failed: 'FAILED',
- canceled: 'CANCELED',
- };
-
- const findAllTab = () => wrapper.findByTestId('jobs-all-tab');
- const findFinishedTab = () => wrapper.findByTestId('jobs-finished-tab');
- const findCancelJobsButton = () => wrapper.findAllComponents(CancelJobs);
-
- const triggerTabChange = (index) => wrapper.findAllComponents(GlTab).at(index).vm.$emit('click');
-
- const createComponent = (props = defaultProps) => {
- wrapper = extendedWrapper(
- mount(JobsTableTabs, {
- provide: {
- jobStatuses: {
- ...statuses,
- },
- },
- propsData: {
- ...props,
- },
- }),
- );
- };
-
- beforeEach(() => {
- createComponent();
- });
-
- it('displays All tab with count', () => {
- expect(trimText(findAllTab().text())).toBe(`All ${defaultProps.allJobsCount}`);
- });
-
- it('displays Finished tab with no count', () => {
- expect(findFinishedTab().text()).toBe('Finished');
- });
-
- it.each`
- tabIndex | expectedScope
- ${0} | ${null}
- ${1} | ${[statuses.success, statuses.failed, statuses.canceled]}
- `('emits fetchJobsByStatus with $expectedScope on tab change', ({ tabIndex, expectedScope }) => {
- triggerTabChange(tabIndex);
-
- expect(wrapper.emitted()).toEqual({ fetchJobsByStatus: [[expectedScope]] });
- });
-
- it('does not displays cancel all jobs button', () => {
- expect(findCancelJobsButton().exists()).toBe(false);
- });
-
- describe('admin mode', () => {
- it('displays cancel all jobs button', () => {
- createComponent(adminProps);
-
- expect(findCancelJobsButton().exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js b/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
deleted file mode 100644
index 098a63719fe..00000000000
--- a/spec/frontend/jobs/mixins/delayed_job_mixin_spec.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import delayedJobFixture from 'test_fixtures/jobs/delayed.json';
-import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
-
-describe('DelayedJobMixin', () => {
- let wrapper;
- const dummyComponent = {
- props: {
- job: {
- type: Object,
- required: true,
- },
- },
- mixins: [delayedJobMixin],
- template: '<div>{{remainingTime}}</div>',
- };
-
- describe('if job is empty object', () => {
- beforeEach(() => {
- wrapper = shallowMount(dummyComponent, {
- propsData: {
- job: {},
- },
- });
- });
-
- it('sets remaining time to 00:00:00', () => {
- expect(wrapper.text()).toBe('00:00:00');
- });
-
- it('does not update remaining time after mounting', async () => {
- await nextTick();
-
- expect(wrapper.text()).toBe('00:00:00');
- });
- });
-
- describe('in REST component', () => {
- describe('if job is delayed job', () => {
- let remainingTimeInMilliseconds = 42000;
-
- beforeEach(async () => {
- jest
- .spyOn(Date, 'now')
- .mockImplementation(
- () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingTimeInMilliseconds,
- );
-
- wrapper = shallowMount(dummyComponent, {
- propsData: {
- job: delayedJobFixture,
- },
- });
-
- await nextTick();
- });
-
- it('sets remaining time', () => {
- expect(wrapper.text()).toBe('00:00:42');
- });
-
- it('updates remaining time', async () => {
- remainingTimeInMilliseconds = 41000;
- jest.advanceTimersByTime(1000);
-
- await nextTick();
- expect(wrapper.text()).toBe('00:00:41');
- });
- });
- });
-
- describe('in GraphQL component', () => {
- const mockGraphQlJob = {
- name: 'build_b',
- scheduledAt: new Date(delayedJobFixture.scheduled_at),
- status: {
- icon: 'status_success',
- tooltip: 'passed',
- hasDetails: true,
- detailsPath: '/root/abcd-dag/-/jobs/1515',
- group: 'success',
- action: null,
- },
- };
-
- describe('if job is delayed job', () => {
- let remainingTimeInMilliseconds = 42000;
-
- beforeEach(async () => {
- jest
- .spyOn(Date, 'now')
- .mockImplementation(
- () => mockGraphQlJob.scheduledAt.getTime() - remainingTimeInMilliseconds,
- );
-
- wrapper = shallowMount(dummyComponent, {
- propsData: {
- job: mockGraphQlJob,
- },
- });
-
- await nextTick();
- });
-
- it('sets remaining time', () => {
- expect(wrapper.text()).toBe('00:00:42');
- });
-
- it('updates remaining time', async () => {
- remainingTimeInMilliseconds = 41000;
- jest.advanceTimersByTime(1000);
-
- await nextTick();
- expect(wrapper.text()).toBe('00:00:41');
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js
deleted file mode 100644
index 253e669e889..00000000000
--- a/spec/frontend/jobs/mock_data.js
+++ /dev/null
@@ -1,1628 +0,0 @@
-import mockJobsCount from 'test_fixtures/graphql/jobs/get_jobs_count.query.graphql.json';
-import mockAllJobsCount from 'test_fixtures/graphql/jobs/get_all_jobs_count.query.graphql.json';
-import mockJobsEmpty from 'test_fixtures/graphql/jobs/get_jobs.query.graphql.empty.json';
-import mockAllJobsEmpty from 'test_fixtures/graphql/jobs/get_all_jobs.query.graphql.empty.json';
-import mockJobsPaginated from 'test_fixtures/graphql/jobs/get_jobs.query.graphql.paginated.json';
-import mockAllJobsPaginated from 'test_fixtures/graphql/jobs/get_all_jobs.query.graphql.paginated.json';
-import mockJobs from 'test_fixtures/graphql/jobs/get_jobs.query.graphql.json';
-import mockAllJobs from 'test_fixtures/graphql/jobs/get_all_jobs.query.graphql.json';
-import mockJobsAsGuest from 'test_fixtures/graphql/jobs/get_jobs.query.graphql.as_guest.json';
-import mockCancelableJobsCount from 'test_fixtures/graphql/jobs/get_cancelable_jobs_count.query.graphql.json';
-import { TEST_HOST } from 'spec/test_constants';
-import { TOKEN_TYPE_STATUS } from '~/vue_shared/components/filtered_search_bar/constants';
-
-const threeWeeksAgo = new Date();
-threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-
-// Fixtures generated at spec/frontend/fixtures/jobs.rb
-export const mockJobsResponsePaginated = mockJobsPaginated;
-export const mockAllJobsResponsePaginated = mockAllJobsPaginated;
-export const mockJobsResponseEmpty = mockJobsEmpty;
-export const mockAllJobsResponseEmpty = mockAllJobsEmpty;
-export const mockJobsNodes = mockJobs.data.project.jobs.nodes;
-export const mockAllJobsNodes = mockAllJobs.data.jobs.nodes;
-export const mockJobsNodesAsGuest = mockJobsAsGuest.data.project.jobs.nodes;
-export const mockJobsCountResponse = mockJobsCount;
-export const mockAllJobsCountResponse = mockAllJobsCount;
-export const mockCancelableJobsCountResponse = mockCancelableJobsCount;
-
-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 const statuses = {
- success: 'SUCCESS',
- failed: 'FAILED',
- canceled: 'CANCELED',
- pending: 'PENDING',
- running: 'RUNNING',
-};
-
-export default {
- id: 4757,
- artifact: {
- locked: false,
- },
- name: 'test',
- stage: 'build',
- 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,
- complete: true,
- created_at: threeWeeksAgo.toISOString(),
- updated_at: threeWeeksAgo.toISOString(),
- finished_at: threeWeeksAgo.toISOString(),
- queued_duration: 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,
- short_sha: 'ABCDEFGH',
- 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 failedJobStatus = {
- 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',
- },
-};
-
-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 const mockPipelineWithoutMR = {
- id: 28029444,
- details: {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- },
- path: 'pipeline/28029444',
- ref: {
- name: 'test-branch',
- },
-};
-
-export const mockPipelineWithoutRef = {
- ...mockPipelineWithoutMR,
- ref: null,
-};
-
-export const mockPipelineWithAttachedMR = {
- id: 28029444,
- details: {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- },
- path: 'pipeline/28029444',
- flags: {
- merge_request_pipeline: true,
- detached_merge_request_pipeline: false,
- },
- merge_request: {
- iid: 1234,
- path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
- title: 'Update README.md',
- source_branch: 'feature-1234',
- source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
- target_branch: 'main',
- target_branch_path: '/root/detached-merge-request-pipelines/branches/main',
- },
- ref: {
- name: 'test-branch',
- },
-};
-
-export const mockPipelineDetached = {
- id: 28029444,
- details: {
- status: {
- details_path: '/gitlab-org/gitlab-foss/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
- },
- path: 'pipeline/28029444',
- flags: {
- merge_request_pipeline: false,
- detached_merge_request_pipeline: true,
- },
- merge_request: {
- iid: 1234,
- path: '/root/detached-merge-request-pipelines/-/merge_requests/1',
- title: 'Update README.md',
- source_branch: 'feature-1234',
- source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
- target_branch: 'main',
- target_branch_path: '/root/detached-merge-request-pipelines/branches/main',
- },
- ref: {
- name: 'test-branch',
- },
-};
-
-export const CIJobConnectionIncomingCache = {
- __typename: 'CiJobConnection',
- pageInfo: {
- __typename: 'PageInfo',
- endCursor: 'eyJpZCI6IjIwNTEifQ',
- hasNextPage: true,
- hasPreviousPage: false,
- startCursor: 'eyJpZCI6IjIxNzMifQ',
- },
- nodes: [
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2057' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2056' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2051' },
- ],
-};
-
-export const CIJobConnectionIncomingCacheRunningStatus = {
- __typename: 'CiJobConnection',
- pageInfo: {
- __typename: 'PageInfo',
- endCursor: 'eyJpZCI6IjIwNTEifQ',
- hasNextPage: true,
- hasPreviousPage: false,
- startCursor: 'eyJpZCI6IjIxNzMifQ',
- },
- nodes: [
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2000' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2001' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2002' },
- ],
-};
-
-export const CIJobConnectionExistingCache = {
- pageInfo: {
- __typename: 'PageInfo',
- endCursor: 'eyJpZCI6IjIwNTEifQ',
- hasNextPage: true,
- hasPreviousPage: false,
- startCursor: 'eyJpZCI6IjIxNzMifQ',
- },
- nodes: [
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2100' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2101' },
- { __ref: 'CiJob:gid://gitlab/Ci::Build/2102' },
- ],
- statuses: 'PENDING',
-};
-
-export const mockFailedSearchToken = {
- type: TOKEN_TYPE_STATUS,
- value: { data: 'FAILED', operator: '=' },
-};
-
-export const retryMutationResponse = {
- data: {
- jobRetry: {
- job: {
- __typename: 'CiJob',
- id: '"gid://gitlab/Ci::Build/1985"',
- detailedStatus: {
- detailsPath: '/root/project/-/jobs/1985',
- id: 'pending-1985-1985',
- __typename: 'DetailedStatus',
- },
- },
- errors: [],
- __typename: 'JobRetryPayload',
- },
- },
-};
-
-export const playMutationResponse = {
- data: {
- jobPlay: {
- job: {
- __typename: 'CiJob',
- id: '"gid://gitlab/Ci::Build/1986"',
- detailedStatus: {
- detailsPath: '/root/project/-/jobs/1986',
- id: 'pending-1986-1986',
- __typename: 'DetailedStatus',
- },
- },
- errors: [],
- __typename: 'JobRetryPayload',
- },
- },
-};
-
-export const cancelMutationResponse = {
- data: {
- jobCancel: {
- job: {
- __typename: 'CiJob',
- id: '"gid://gitlab/Ci::Build/1987"',
- detailedStatus: {
- detailsPath: '/root/project/-/jobs/1987',
- id: 'pending-1987-1987',
- __typename: 'DetailedStatus',
- },
- },
- errors: [],
- __typename: 'JobRetryPayload',
- },
- },
-};
-
-export const unscheduleMutationResponse = {
- data: {
- jobUnschedule: {
- job: {
- __typename: 'CiJob',
- id: '"gid://gitlab/Ci::Build/1988"',
- detailedStatus: {
- detailsPath: '/root/project/-/jobs/1988',
- id: 'pending-1988-1988',
- __typename: 'DetailedStatus',
- },
- },
- errors: [],
- __typename: 'JobRetryPayload',
- },
- },
-};
-
-export const mockJobLog = [
- { offset: 0, content: [{ text: 'Running with gitlab-runner 15.0.0 (febb2a09)' }], lineNumber: 0 },
- { offset: 54, content: [{ text: ' on colima-docker EwM9WzgD' }], lineNumber: 1 },
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 91,
- content: [{ text: 'Resolving secrets', style: 'term-fg-l-cyan term-bold' }],
- section: 'resolve-secrets',
- section_header: true,
- lineNumber: 2,
- section_duration: '00:00',
- },
- lines: [],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 218,
- content: [{ text: 'Preparing the "docker" executor', style: 'term-fg-l-cyan term-bold' }],
- section: 'prepare-executor',
- section_header: true,
- lineNumber: 4,
- section_duration: '00:01',
- },
- lines: [
- {
- offset: 317,
- content: [{ text: 'Using Docker executor with image ruby:2.7 ...' }],
- section: 'prepare-executor',
- lineNumber: 5,
- },
- {
- offset: 372,
- content: [{ text: 'Pulling docker image ruby:2.7 ...' }],
- section: 'prepare-executor',
- lineNumber: 6,
- },
- {
- offset: 415,
- content: [
- {
- text:
- 'Using docker image sha256:55106bf6ba7f452c38d01ea760affc6ceb67d4b60068ffadab98d1b7b007668c for ruby:2.7 with digest ruby@sha256:23d08a4bae1a12ee3fce017f83204fcf9a02243443e4a516e65e5ff73810a449 ...',
- },
- ],
- section: 'prepare-executor',
- lineNumber: 7,
- },
- ],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 665,
- content: [{ text: 'Preparing environment', style: 'term-fg-l-cyan term-bold' }],
- section: 'prepare-script',
- section_header: true,
- lineNumber: 9,
- section_duration: '00:01',
- },
- lines: [
- {
- offset: 752,
- content: [
- { text: 'Running on runner-ewm9wzgd-project-20-concurrent-0 via 8ea689ec6969...' },
- ],
- section: 'prepare-script',
- lineNumber: 10,
- },
- ],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 865,
- content: [{ text: 'Getting source from Git repository', style: 'term-fg-l-cyan term-bold' }],
- section: 'get-sources',
- section_header: true,
- lineNumber: 12,
- section_duration: '00:01',
- },
- lines: [
- {
- offset: 962,
- content: [
- {
- text: 'Fetching changes with git depth set to 20...',
- style: 'term-fg-l-green term-bold',
- },
- ],
- section: 'get-sources',
- lineNumber: 13,
- },
- {
- offset: 1019,
- content: [
- { text: 'Reinitialized existing Git repository in /builds/root/ci-project/.git/' },
- ],
- section: 'get-sources',
- lineNumber: 14,
- },
- {
- offset: 1090,
- content: [{ text: 'Checking out e0f63d76 as main...', style: 'term-fg-l-green term-bold' }],
- section: 'get-sources',
- lineNumber: 15,
- },
- {
- offset: 1136,
- content: [{ text: 'Skipping Git submodules setup', style: 'term-fg-l-green term-bold' }],
- section: 'get-sources',
- lineNumber: 16,
- },
- ],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 1217,
- content: [
- {
- text: 'Executing "step_script" stage of the job script',
- style: 'term-fg-l-cyan term-bold',
- },
- ],
- section: 'step-script',
- section_header: true,
- lineNumber: 18,
- section_duration: '00:00',
- },
- lines: [
- {
- offset: 1327,
- content: [
- {
- text:
- 'Using docker image sha256:55106bf6ba7f452c38d01ea760affc6ceb67d4b60068ffadab98d1b7b007668c for ruby:2.7 with digest ruby@sha256:23d08a4bae1a12ee3fce017f83204fcf9a02243443e4a516e65e5ff73810a449 ...',
- },
- ],
- section: 'step-script',
- lineNumber: 19,
- },
- {
- offset: 1533,
- content: [{ text: '$ echo "82.71"', style: 'term-fg-l-green term-bold' }],
- section: 'step-script',
- lineNumber: 20,
- },
- { offset: 1560, content: [{ text: '82.71' }], section: 'step-script', lineNumber: 21 },
- ],
- },
- {
- offset: 1605,
- content: [{ text: 'Job succeeded', style: 'term-fg-l-green term-bold' }],
- lineNumber: 23,
- },
-];
diff --git a/spec/frontend/jobs/store/actions_spec.js b/spec/frontend/jobs/store/actions_spec.js
deleted file mode 100644
index 73a158d52d8..00000000000
--- a/spec/frontend/jobs/store/actions_spec.js
+++ /dev/null
@@ -1,502 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'helpers/test_constants';
-import testAction from 'helpers/vuex_action_helper';
-import {
- setJobEndpoint,
- setJobLogOptions,
- clearEtagPoll,
- stopPolling,
- requestJob,
- fetchJob,
- receiveJobSuccess,
- receiveJobError,
- scrollTop,
- scrollBottom,
- requestJobLog,
- fetchJobLog,
- startPollingJobLog,
- stopPollingJobLog,
- receiveJobLogSuccess,
- receiveJobLogError,
- toggleCollapsibleLine,
- requestJobsForStage,
- fetchJobsForStage,
- receiveJobsForStageSuccess,
- receiveJobsForStageError,
- hideSidebar,
- showSidebar,
- toggleSidebar,
-} from '~/jobs/store/actions';
-import * as types from '~/jobs/store/mutation_types';
-import state from '~/jobs/store/state';
-import axios from '~/lib/utils/axios_utils';
-import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
-
-describe('Job State actions', () => {
- let mockedState;
-
- beforeEach(() => {
- mockedState = state();
- });
-
- describe('setJobEndpoint', () => {
- it('should commit SET_JOB_ENDPOINT mutation', () => {
- return testAction(
- setJobEndpoint,
- 'job/872324.json',
- mockedState,
- [{ type: types.SET_JOB_ENDPOINT, payload: 'job/872324.json' }],
- [],
- );
- });
- });
-
- describe('setJobLogOptions', () => {
- it('should commit SET_JOB_LOG_OPTIONS mutation', () => {
- return testAction(
- setJobLogOptions,
- { pagePath: 'job/872324/trace.json' },
- mockedState,
- [{ type: types.SET_JOB_LOG_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }],
- [],
- );
- });
- });
-
- describe('hideSidebar', () => {
- it('should commit HIDE_SIDEBAR mutation', () => {
- return testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], []);
- });
- });
-
- describe('showSidebar', () => {
- it('should commit SHOW_SIDEBAR mutation', () => {
- return testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], []);
- });
- });
-
- describe('toggleSidebar', () => {
- describe('when isSidebarOpen is true', () => {
- it('should dispatch hideSidebar', () => {
- return testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }]);
- });
- });
-
- describe('when isSidebarOpen is false', () => {
- it('should dispatch showSidebar', () => {
- mockedState.isSidebarOpen = false;
-
- return testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }]);
- });
- });
- });
-
- describe('requestJob', () => {
- it('should commit REQUEST_JOB mutation', () => {
- return testAction(requestJob, null, mockedState, [{ type: types.REQUEST_JOB }], []);
- });
- });
-
- describe('fetchJob', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.jobEndpoint = `${TEST_HOST}/endpoint.json`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestJob and receiveJobSuccess', () => {
- mock
- .onGet(`${TEST_HOST}/endpoint.json`)
- .replyOnce(HTTP_STATUS_OK, { id: 121212, name: 'karma' });
-
- return testAction(
- fetchJob,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestJob',
- },
- {
- payload: { id: 121212, name: 'karma' },
- type: 'receiveJobSuccess',
- },
- ],
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
- });
-
- it('dispatches requestJob and receiveJobError', () => {
- return testAction(
- fetchJob,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestJob',
- },
- {
- type: 'receiveJobError',
- },
- ],
- );
- });
- });
- });
-
- describe('receiveJobSuccess', () => {
- it('should commit RECEIVE_JOB_SUCCESS mutation', () => {
- return testAction(
- receiveJobSuccess,
- { id: 121232132 },
- mockedState,
- [{ type: types.RECEIVE_JOB_SUCCESS, payload: { id: 121232132 } }],
- [],
- );
- });
- });
-
- describe('receiveJobError', () => {
- it('should commit RECEIVE_JOB_ERROR mutation', () => {
- return testAction(
- receiveJobError,
- null,
- mockedState,
- [{ type: types.RECEIVE_JOB_ERROR }],
- [],
- );
- });
- });
-
- describe('scrollTop', () => {
- it('should dispatch toggleScrollButtons action', () => {
- return testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }]);
- });
- });
-
- describe('scrollBottom', () => {
- it('should dispatch toggleScrollButtons action', () => {
- return testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }]);
- });
- });
-
- describe('requestJobLog', () => {
- it('should commit REQUEST_JOB_LOG mutation', () => {
- return testAction(requestJobLog, null, mockedState, [{ type: types.REQUEST_JOB_LOG }], []);
- });
- });
-
- describe('fetchJobLog', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.jobLogEndpoint = `${TEST_HOST}/endpoint`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- stopPolling();
- clearEtagPoll();
- });
-
- describe('success', () => {
- it('dispatches requestJobLog, receiveJobLogSuccess and stopPollingJobLog when job is complete', () => {
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(HTTP_STATUS_OK, {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: true,
- });
-
- return testAction(
- fetchJobLog,
- null,
- mockedState,
- [],
- [
- {
- type: 'toggleScrollisInBottom',
- payload: true,
- },
- {
- payload: {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: true,
- },
- type: 'receiveJobLogSuccess',
- },
- {
- type: 'stopPollingJobLog',
- },
- ],
- );
- });
-
- describe('when job is incomplete', () => {
- let jobLogPayload;
-
- beforeEach(() => {
- jobLogPayload = {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
- complete: false,
- };
-
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(HTTP_STATUS_OK, jobLogPayload);
- });
-
- it('dispatches startPollingJobLog', () => {
- return testAction(
- fetchJobLog,
- null,
- mockedState,
- [],
- [
- { type: 'toggleScrollisInBottom', payload: true },
- { type: 'receiveJobLogSuccess', payload: jobLogPayload },
- { type: 'startPollingJobLog' },
- ],
- );
- });
-
- it('does not dispatch startPollingJobLog when timeout is non-empty', () => {
- mockedState.jobLogTimeout = 1;
-
- return testAction(
- fetchJobLog,
- null,
- mockedState,
- [],
- [
- { type: 'toggleScrollisInBottom', payload: true },
- { type: 'receiveJobLogSuccess', payload: jobLogPayload },
- ],
- );
- });
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint/trace.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
- });
-
- it('dispatches requestJobLog and receiveJobLogError', () => {
- return testAction(
- fetchJobLog,
- null,
- mockedState,
- [],
- [
- {
- type: 'receiveJobLogError',
- },
- ],
- );
- });
- });
- });
-
- describe('startPollingJobLog', () => {
- let dispatch;
- let commit;
-
- beforeEach(() => {
- dispatch = jest.fn();
- commit = jest.fn();
-
- startPollingJobLog({ dispatch, commit });
- });
-
- afterEach(() => {
- jest.clearAllTimers();
- });
-
- it('should save the timeout id but not call fetchJobLog', () => {
- expect(commit).toHaveBeenCalledWith(types.SET_JOB_LOG_TIMEOUT, expect.any(Number));
- expect(commit.mock.calls[0][1]).toBeGreaterThan(0);
-
- expect(dispatch).not.toHaveBeenCalledWith('fetchJobLog');
- });
-
- describe('after timeout has passed', () => {
- beforeEach(() => {
- jest.advanceTimersByTime(4000);
- });
-
- it('should clear the timeout id and fetchJobLog', () => {
- expect(commit).toHaveBeenCalledWith(types.SET_JOB_LOG_TIMEOUT, 0);
- expect(dispatch).toHaveBeenCalledWith('fetchJobLog');
- });
- });
- });
-
- describe('stopPollingJobLog', () => {
- let origTimeout;
-
- beforeEach(() => {
- // Can't use spyOn(window, 'clearTimeout') because this caused unrelated specs to timeout
- // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23838#note_280277727
- origTimeout = window.clearTimeout;
- window.clearTimeout = jest.fn();
- });
-
- afterEach(() => {
- window.clearTimeout = origTimeout;
- });
-
- it('should commit STOP_POLLING_JOB_LOG mutation', async () => {
- const jobLogTimeout = 7;
-
- await testAction(
- stopPollingJobLog,
- null,
- { ...mockedState, jobLogTimeout },
- [{ type: types.SET_JOB_LOG_TIMEOUT, payload: 0 }, { type: types.STOP_POLLING_JOB_LOG }],
- [],
- );
- expect(window.clearTimeout).toHaveBeenCalledWith(jobLogTimeout);
- });
- });
-
- describe('receiveJobLogSuccess', () => {
- it('should commit RECEIVE_JOB_LOG_SUCCESS mutation', () => {
- return testAction(
- receiveJobLogSuccess,
- 'hello world',
- mockedState,
- [{ type: types.RECEIVE_JOB_LOG_SUCCESS, payload: 'hello world' }],
- [],
- );
- });
- });
-
- describe('receiveJobLogError', () => {
- it('should commit stop polling job log', () => {
- return testAction(receiveJobLogError, null, mockedState, [], [{ type: 'stopPollingJobLog' }]);
- });
- });
-
- describe('toggleCollapsibleLine', () => {
- it('should commit TOGGLE_COLLAPSIBLE_LINE mutation', () => {
- return testAction(
- toggleCollapsibleLine,
- { isClosed: true },
- mockedState,
- [{ type: types.TOGGLE_COLLAPSIBLE_LINE, payload: { isClosed: true } }],
- [],
- );
- });
- });
-
- describe('requestJobsForStage', () => {
- it('should commit REQUEST_JOBS_FOR_STAGE mutation', () => {
- return testAction(
- requestJobsForStage,
- { name: 'deploy' },
- mockedState,
- [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }],
- [],
- );
- });
- });
-
- describe('fetchJobsForStage', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('success', () => {
- it('dispatches requestJobsForStage and receiveJobsForStageSuccess', () => {
- mock.onGet(`${TEST_HOST}/jobs.json`).replyOnce(HTTP_STATUS_OK, {
- latest_statuses: [{ id: 121212, name: 'build' }],
- retried: [],
- });
-
- return testAction(
- fetchJobsForStage,
- { dropdown_path: `${TEST_HOST}/jobs.json` },
- mockedState,
- [],
- [
- {
- type: 'requestJobsForStage',
- payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
- },
- {
- payload: [{ id: 121212, name: 'build' }],
- type: 'receiveJobsForStageSuccess',
- },
- ],
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/jobs.json`).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR);
- });
-
- it('dispatches requestJobsForStage and receiveJobsForStageError', () => {
- return testAction(
- fetchJobsForStage,
- { dropdown_path: `${TEST_HOST}/jobs.json` },
- mockedState,
- [],
- [
- {
- type: 'requestJobsForStage',
- payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
- },
- {
- type: 'receiveJobsForStageError',
- },
- ],
- );
- });
- });
- });
-
- describe('receiveJobsForStageSuccess', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_SUCCESS mutation', () => {
- return testAction(
- receiveJobsForStageSuccess,
- [{ id: 121212, name: 'karma' }],
- mockedState,
- [{ type: types.RECEIVE_JOBS_FOR_STAGE_SUCCESS, payload: [{ id: 121212, name: 'karma' }] }],
- [],
- );
- });
- });
-
- describe('receiveJobsForStageError', () => {
- it('should commit RECEIVE_JOBS_FOR_STAGE_ERROR mutation', () => {
- return testAction(
- receiveJobsForStageError,
- null,
- mockedState,
- [{ type: types.RECEIVE_JOBS_FOR_STAGE_ERROR }],
- [],
- );
- });
- });
-});
diff --git a/spec/frontend/jobs/store/getters_spec.js b/spec/frontend/jobs/store/getters_spec.js
deleted file mode 100644
index c13b051c672..00000000000
--- a/spec/frontend/jobs/store/getters_spec.js
+++ /dev/null
@@ -1,245 +0,0 @@
-import * as getters from '~/jobs/store/getters';
-import state from '~/jobs/store/state';
-
-describe('Job Store Getters', () => {
- let localState;
-
- beforeEach(() => {
- localState = state();
- });
-
- describe('headerTime', () => {
- describe('when the job has started key', () => {
- it('returns started_at value', () => {
- const started = '2018-08-31T16:20:49.023Z';
- const startedAt = '2018-08-31T16:20:49.023Z';
- localState.job.started_at = startedAt;
- localState.job.started = started;
-
- expect(getters.headerTime(localState)).toEqual(startedAt);
- });
- });
-
- describe('when the job does not have started key', () => {
- it('returns created_at value', () => {
- const created = '2018-08-31T16:20:49.023Z';
- localState.job.created_at = created;
-
- expect(getters.headerTime(localState)).toEqual(created);
- });
- });
- });
-
- describe('shouldRenderCalloutMessage', () => {
- describe('with status and callout message', () => {
- it('returns true', () => {
- localState.job.callout_message = 'Callout message';
- localState.job.status = { icon: 'passed' };
-
- expect(getters.shouldRenderCalloutMessage(localState)).toEqual(true);
- });
- });
-
- describe('without status & with callout message', () => {
- it('returns false', () => {
- localState.job.callout_message = 'Callout message';
-
- expect(getters.shouldRenderCalloutMessage(localState)).toEqual(false);
- });
- });
-
- describe('with status & without callout message', () => {
- it('returns false', () => {
- localState.job.status = { icon: 'passed' };
-
- expect(getters.shouldRenderCalloutMessage(localState)).toEqual(false);
- });
- });
- });
-
- describe('shouldRenderTriggeredLabel', () => {
- describe('when started equals null', () => {
- it('returns false', () => {
- localState.job.started_at = null;
-
- expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(false);
- });
- });
-
- describe('when started equals string', () => {
- it('returns true', () => {
- localState.job.started_at = '2018-08-31T16:20:49.023Z';
-
- expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(true);
- });
- });
- });
-
- describe('hasEnvironment', () => {
- describe('without `deployment_status`', () => {
- it('returns false', () => {
- expect(getters.hasEnvironment(localState)).toEqual(false);
- });
- });
-
- describe('with an empty object for `deployment_status`', () => {
- it('returns false', () => {
- localState.job.deployment_status = {};
-
- expect(getters.hasEnvironment(localState)).toEqual(false);
- });
- });
-
- describe('when `deployment_status` is defined and not empty', () => {
- it('returns true', () => {
- localState.job.deployment_status = {
- status: 'creating',
- environment: {
- last_deployment: {},
- },
- };
-
- expect(getters.hasEnvironment(localState)).toEqual(true);
- });
- });
- });
-
- describe('hasJobLog', () => {
- describe('when has_trace is true', () => {
- it('returns true', () => {
- localState.job.has_trace = true;
- localState.job.status = {};
-
- expect(getters.hasJobLog(localState)).toEqual(true);
- });
- });
-
- describe('when job is running', () => {
- it('returns true', () => {
- localState.job.has_trace = false;
- localState.job.status = { group: 'running' };
-
- expect(getters.hasJobLog(localState)).toEqual(true);
- });
- });
-
- describe('when has_trace is false and job is not running', () => {
- it('returns false', () => {
- localState.job.has_trace = false;
- localState.job.status = { group: 'pending' };
-
- expect(getters.hasJobLog(localState)).toEqual(false);
- });
- });
- });
-
- describe('emptyStateIllustration', () => {
- describe('with defined illustration', () => {
- it('returns the state illustration object', () => {
- localState.job.status = {
- illustration: {
- path: 'foo',
- },
- };
-
- expect(getters.emptyStateIllustration(localState)).toEqual({ path: 'foo' });
- });
- });
-
- describe('when illustration is not defined', () => {
- it('returns an empty object', () => {
- expect(getters.emptyStateIllustration(localState)).toEqual({});
- });
- });
- });
-
- describe('shouldRenderSharedRunnerLimitWarning', () => {
- describe('without runners information', () => {
- it('returns false', () => {
- expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(false);
- });
- });
-
- describe('with runners information', () => {
- describe('when used quota is less than limit', () => {
- it('returns false', () => {
- localState.job.runners = {
- quota: {
- used: 33,
- limit: 2000,
- },
- available: true,
- online: true,
- };
-
- expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(false);
- });
- });
-
- describe('when used quota is equal to limit', () => {
- it('returns true', () => {
- localState.job.runners = {
- quota: {
- used: 2000,
- limit: 2000,
- },
- available: true,
- online: true,
- };
-
- expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(true);
- });
- });
-
- describe('when used quota is bigger than limit', () => {
- it('returns true', () => {
- localState.job.runners = {
- quota: {
- used: 2002,
- limit: 2000,
- },
- available: true,
- online: true,
- };
-
- expect(getters.shouldRenderSharedRunnerLimitWarning(localState)).toEqual(true);
- });
- });
- });
- });
-
- describe('hasOfflineRunnersForProject', () => {
- describe('with available and offline runners', () => {
- it('returns true', () => {
- localState.job.runners = {
- available: true,
- online: false,
- };
-
- expect(getters.hasOfflineRunnersForProject(localState)).toEqual(true);
- });
- });
-
- describe('with non available runners', () => {
- it('returns false', () => {
- localState.job.runners = {
- available: false,
- online: false,
- };
-
- expect(getters.hasOfflineRunnersForProject(localState)).toEqual(false);
- });
- });
-
- describe('with online runners', () => {
- it('returns false', () => {
- localState.job.runners = {
- available: false,
- online: true,
- };
-
- expect(getters.hasOfflineRunnersForProject(localState)).toEqual(false);
- });
- });
- });
-});
diff --git a/spec/frontend/jobs/store/helpers.js b/spec/frontend/jobs/store/helpers.js
deleted file mode 100644
index 402ae58971a..00000000000
--- a/spec/frontend/jobs/store/helpers.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import state from '~/jobs/store/state';
-
-export const resetStore = (store) => {
- store.replaceState(state());
-};
diff --git a/spec/frontend/jobs/store/mutations_spec.js b/spec/frontend/jobs/store/mutations_spec.js
deleted file mode 100644
index 89cda3b0544..00000000000
--- a/spec/frontend/jobs/store/mutations_spec.js
+++ /dev/null
@@ -1,269 +0,0 @@
-import * as types from '~/jobs/store/mutation_types';
-import mutations from '~/jobs/store/mutations';
-import state from '~/jobs/store/state';
-
-describe('Jobs Store Mutations', () => {
- let stateCopy;
-
- const html =
- 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- : Writing /builds/ab89e95b0fa0b9272ea0c797b76908f24d36992630e9325273a4ce3.png<br>I';
-
- beforeEach(() => {
- stateCopy = state();
- });
-
- describe('SET_JOB_ENDPOINT', () => {
- it('should set jobEndpoint', () => {
- mutations[types.SET_JOB_ENDPOINT](stateCopy, 'job/21312321.json');
-
- expect(stateCopy.jobEndpoint).toEqual('job/21312321.json');
- });
- });
-
- describe('HIDE_SIDEBAR', () => {
- it('should set isSidebarOpen to false', () => {
- mutations[types.HIDE_SIDEBAR](stateCopy);
-
- expect(stateCopy.isSidebarOpen).toEqual(false);
- });
- });
-
- describe('SHOW_SIDEBAR', () => {
- it('should set isSidebarOpen to true', () => {
- mutations[types.SHOW_SIDEBAR](stateCopy);
-
- expect(stateCopy.isSidebarOpen).toEqual(true);
- });
- });
-
- describe('RECEIVE_JOB_LOG_SUCCESS', () => {
- describe('when job log has state', () => {
- it('sets jobLogState', () => {
- const stateLog =
- 'eyJvZmZzZXQiOjczNDQ1MSwibl9vcGVuX3RhZ3MiOjAsImZnX2NvbG9yIjpudWxsLCJiZ19jb2xvciI6bnVsbCwic3R5bGVfbWFzayI6MH0=';
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, {
- state: stateLog,
- });
-
- expect(stateCopy.jobLogState).toEqual(stateLog);
- });
- });
-
- describe('when jobLogSize is smaller than the total size', () => {
- it('sets isJobLogSizeVisible to true', () => {
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, { total: 51184600, size: 1231 });
-
- expect(stateCopy.isJobLogSizeVisible).toEqual(true);
- });
- });
-
- describe('when jobLogSize is bigger than the total size', () => {
- it('sets isJobLogSizeVisible to false', () => {
- const copy = { ...stateCopy, jobLogSize: 5118460, size: 2321312 };
-
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](copy, { total: 511846 });
-
- expect(copy.isJobLogSizeVisible).toEqual(false);
- });
- });
-
- it('sets job log size and isJobLogComplete', () => {
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, {
- append: true,
- html,
- size: 511846,
- complete: true,
- lines: [],
- });
-
- expect(stateCopy.jobLogSize).toEqual(511846);
- expect(stateCopy.isJobLogComplete).toEqual(true);
- });
-
- describe('with new job log', () => {
- describe('log.lines', () => {
- describe('when append is true', () => {
- it('sets the parsed log', () => {
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, {
- append: true,
- size: 511846,
- complete: true,
- lines: [
- {
- offset: 1,
- content: [{ text: 'Running with gitlab-runner 11.12.1 (5a147c92)' }],
- },
- ],
- });
-
- expect(stateCopy.jobLog).toEqual([
- {
- offset: 1,
- content: [{ text: 'Running with gitlab-runner 11.12.1 (5a147c92)' }],
- lineNumber: 0,
- },
- ]);
- });
- });
-
- describe('when it is defined', () => {
- it('sets the parsed log', () => {
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, {
- append: false,
- size: 511846,
- complete: true,
- lines: [
- { offset: 0, content: [{ text: 'Running with gitlab-runner 11.11.1 (5a147c92)' }] },
- ],
- });
-
- expect(stateCopy.jobLog).toEqual([
- {
- offset: 0,
- content: [{ text: 'Running with gitlab-runner 11.11.1 (5a147c92)' }],
- lineNumber: 0,
- },
- ]);
- });
- });
-
- describe('when it is null', () => {
- it('sets the default value', () => {
- mutations[types.RECEIVE_JOB_LOG_SUCCESS](stateCopy, {
- append: true,
- html,
- size: 511846,
- complete: false,
- lines: null,
- });
-
- expect(stateCopy.jobLog).toEqual([]);
- });
- });
- });
- });
- });
-
- describe('SET_JOB_LOG_TIMEOUT', () => {
- it('sets the jobLogTimeout id', () => {
- const id = 7;
-
- expect(stateCopy.jobLogTimeout).not.toEqual(id);
-
- mutations[types.SET_JOB_LOG_TIMEOUT](stateCopy, id);
-
- expect(stateCopy.jobLogTimeout).toEqual(id);
- });
- });
-
- describe('STOP_POLLING_JOB_LOG', () => {
- it('sets isJobLogComplete to true', () => {
- mutations[types.STOP_POLLING_JOB_LOG](stateCopy);
-
- expect(stateCopy.isJobLogComplete).toEqual(true);
- });
- });
-
- describe('TOGGLE_COLLAPSIBLE_LINE', () => {
- it('toggles the `isClosed` property of the provided object', () => {
- const section = { isClosed: true };
- mutations[types.TOGGLE_COLLAPSIBLE_LINE](stateCopy, section);
- expect(section.isClosed).toEqual(false);
- });
- });
-
- describe('REQUEST_JOB', () => {
- it('sets isLoading to true', () => {
- mutations[types.REQUEST_JOB](stateCopy);
-
- expect(stateCopy.isLoading).toEqual(true);
- });
- });
-
- describe('RECEIVE_JOB_SUCCESS', () => {
- it('sets is loading to false', () => {
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
-
- expect(stateCopy.isLoading).toEqual(false);
- });
-
- it('sets hasError to false', () => {
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
-
- expect(stateCopy.hasError).toEqual(false);
- });
-
- it('sets job data', () => {
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
-
- expect(stateCopy.job).toEqual({ id: 1312321 });
- });
-
- it('sets selectedStage when the selectedStage is empty', () => {
- expect(stateCopy.selectedStage).toEqual('');
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
-
- expect(stateCopy.selectedStage).toEqual('deploy');
- });
-
- it('does not set selectedStage when the selectedStage is not More', () => {
- stateCopy.selectedStage = 'notify';
-
- expect(stateCopy.selectedStage).toEqual('notify');
- mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
-
- expect(stateCopy.selectedStage).toEqual('notify');
- });
- });
-
- describe('RECEIVE_JOB_ERROR', () => {
- it('resets job data', () => {
- mutations[types.RECEIVE_JOB_ERROR](stateCopy);
-
- expect(stateCopy.isLoading).toEqual(false);
- expect(stateCopy.job).toEqual({});
- });
- });
-
- describe('REQUEST_JOBS_FOR_STAGE', () => {
- it('sets isLoadingJobs to true', () => {
- mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
-
- expect(stateCopy.isLoadingJobs).toEqual(true);
- });
-
- it('sets selectedStage', () => {
- mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
-
- expect(stateCopy.selectedStage).toEqual('deploy');
- });
- });
-
- describe('RECEIVE_JOBS_FOR_STAGE_SUCCESS', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_JOBS_FOR_STAGE_SUCCESS](stateCopy, [{ name: 'karma' }]);
- });
-
- it('sets isLoadingJobs to false', () => {
- expect(stateCopy.isLoadingJobs).toEqual(false);
- });
-
- it('sets jobs', () => {
- expect(stateCopy.jobs).toEqual([{ name: 'karma' }]);
- });
- });
-
- describe('RECEIVE_JOBS_FOR_STAGE_ERROR', () => {
- beforeEach(() => {
- mutations[types.RECEIVE_JOBS_FOR_STAGE_ERROR](stateCopy);
- });
-
- it('sets isLoadingJobs to false', () => {
- expect(stateCopy.isLoadingJobs).toEqual(false);
- });
-
- it('resets jobs', () => {
- expect(stateCopy.jobs).toEqual([]);
- });
- });
-});
diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js
deleted file mode 100644
index 37a6722c555..00000000000
--- a/spec/frontend/jobs/store/utils_spec.js
+++ /dev/null
@@ -1,510 +0,0 @@
-import {
- logLinesParser,
- updateIncrementalJobLog,
- parseHeaderLine,
- parseLine,
- addDurationToHeader,
- isCollapsibleSection,
- findOffsetAndRemove,
- getIncrementalLineNumber,
-} from '~/jobs/store/utils';
-import {
- utilsMockData,
- originalTrace,
- regularIncremental,
- regularIncrementalRepeated,
- headerTrace,
- headerTraceIncremental,
- collapsibleTrace,
- collapsibleTraceIncremental,
-} from '../components/log/mock_data';
-
-describe('Jobs Store Utils', () => {
- describe('parseHeaderLine', () => {
- it('returns a new object with the header keys and the provided line parsed', () => {
- const headerLine = { content: [{ text: 'foo' }] };
- const parsedHeaderLine = parseHeaderLine(headerLine, 2);
-
- expect(parsedHeaderLine).toEqual({
- isClosed: false,
- isHeader: true,
- line: {
- ...headerLine,
- lineNumber: 2,
- },
- lines: [],
- });
- });
-
- it('pre-closes a section when specified in options', () => {
- const headerLine = { content: [{ text: 'foo' }], section_options: { collapsed: 'true' } };
-
- const parsedHeaderLine = parseHeaderLine(headerLine, 2);
-
- expect(parsedHeaderLine.isClosed).toBe(true);
- });
-
- it('expands all pre-closed sections if hash is present', () => {
- const headerLine = { content: [{ text: 'foo' }], section_options: { collapsed: 'true' } };
-
- const parsedHeaderLine = parseHeaderLine(headerLine, 2, '#L33');
-
- expect(parsedHeaderLine.isClosed).toBe(false);
- });
- });
-
- describe('parseLine', () => {
- it('returns a new object with the lineNumber key added to the provided line object', () => {
- const line = { content: [{ text: 'foo' }] };
- const parsed = parseLine(line, 1);
- expect(parsed.content).toEqual(line.content);
- expect(parsed.lineNumber).toEqual(1);
- });
- });
-
- describe('addDurationToHeader', () => {
- const duration = {
- offset: 106,
- content: [],
- section: 'prepare-script',
- section_duration: '00:03',
- };
-
- it('adds the section duration to the correct header', () => {
- const parsed = [
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'prepare-script',
- content: [{ text: 'foo' }],
- },
- lines: [],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'foo-bar',
- content: [{ text: 'foo' }],
- },
- lines: [],
- },
- ];
-
- addDurationToHeader(parsed, duration);
-
- expect(parsed[0].line.section_duration).toEqual(duration.section_duration);
- expect(parsed[1].line.section_duration).toEqual(undefined);
- });
-
- it('does not add the section duration when the headers do not match', () => {
- const parsed = [
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'bar-foo',
- content: [{ text: 'foo' }],
- },
- lines: [],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'foo-bar',
- content: [{ text: 'foo' }],
- },
- lines: [],
- },
- ];
- addDurationToHeader(parsed, duration);
-
- expect(parsed[0].line.section_duration).toEqual(undefined);
- expect(parsed[1].line.section_duration).toEqual(undefined);
- });
-
- it('does not add when content has no headers', () => {
- const parsed = [
- {
- section: 'bar-foo',
- content: [{ text: 'foo' }],
- lineNumber: 1,
- },
- {
- section: 'foo-bar',
- content: [{ text: 'foo' }],
- lineNumber: 2,
- },
- ];
-
- addDurationToHeader(parsed, duration);
-
- expect(parsed[0].line).toEqual(undefined);
- expect(parsed[1].line).toEqual(undefined);
- });
- });
-
- describe('isCollapsibleSection', () => {
- const header = {
- isHeader: true,
- line: {
- section: 'foo',
- },
- };
- const line = {
- lineNumber: 1,
- section: 'foo',
- content: [],
- };
-
- it('returns true when line belongs to the last section', () => {
- expect(isCollapsibleSection([header], header, { section: 'foo', content: [] })).toEqual(true);
- });
-
- it('returns false when last line was not an header', () => {
- expect(isCollapsibleSection([line], line, { section: 'bar' })).toEqual(false);
- });
-
- it('returns false when accumulator is empty', () => {
- expect(isCollapsibleSection([], { isHeader: true }, { section: 'bar' })).toEqual(false);
- });
-
- it('returns false when section_duration is defined', () => {
- expect(isCollapsibleSection([header], header, { section_duration: '10:00' })).toEqual(false);
- });
-
- it('returns false when `section` is not a match', () => {
- expect(isCollapsibleSection([header], header, { section: 'bar' })).toEqual(false);
- });
-
- it('returns false when no parameters are provided', () => {
- expect(isCollapsibleSection()).toEqual(false);
- });
- });
- describe('logLinesParser', () => {
- let result;
-
- beforeEach(() => {
- result = logLinesParser(utilsMockData);
- });
-
- describe('regular line', () => {
- it('adds a lineNumber property with correct index', () => {
- expect(result[0].lineNumber).toEqual(0);
- expect(result[1].line.lineNumber).toEqual(1);
- });
- });
-
- describe('collapsible section', () => {
- it('adds a `isClosed` property', () => {
- expect(result[1].isClosed).toEqual(false);
- });
-
- it('adds a `isHeader` property', () => {
- expect(result[1].isHeader).toEqual(true);
- });
-
- it('creates a lines array property with the content of the collapsible section', () => {
- expect(result[1].lines.length).toEqual(2);
- expect(result[1].lines[0].content).toEqual(utilsMockData[2].content);
- expect(result[1].lines[1].content).toEqual(utilsMockData[3].content);
- });
- });
-
- describe('section duration', () => {
- it('adds the section information to the header section', () => {
- expect(result[1].line.section_duration).toEqual(utilsMockData[4].section_duration);
- });
-
- it('does not add section duration as a line', () => {
- expect(result[1].lines.includes(utilsMockData[4])).toEqual(false);
- });
- });
- });
-
- describe('findOffsetAndRemove', () => {
- describe('when last item is header', () => {
- const existingLog = [
- {
- isHeader: true,
- isClosed: false,
- line: { content: [{ text: 'bar' }], offset: 10, lineNumber: 1 },
- },
- ];
-
- describe('and matches the offset', () => {
- it('returns an array with the item removed', () => {
- const newData = [{ offset: 10, content: [{ text: 'foobar' }] }];
- const result = findOffsetAndRemove(newData, existingLog);
-
- expect(result).toEqual([]);
- });
- });
-
- describe('and does not match the offset', () => {
- it('returns the provided existing log', () => {
- const newData = [{ offset: 110, content: [{ text: 'foobar' }] }];
- const result = findOffsetAndRemove(newData, existingLog);
-
- expect(result).toEqual(existingLog);
- });
- });
- });
-
- describe('when last item is a regular line', () => {
- const existingLog = [{ content: [{ text: 'bar' }], offset: 10, lineNumber: 1 }];
-
- describe('and matches the offset', () => {
- it('returns an array with the item removed', () => {
- const newData = [{ offset: 10, content: [{ text: 'foobar' }] }];
- const result = findOffsetAndRemove(newData, existingLog);
-
- expect(result).toEqual([]);
- });
- });
-
- describe('and does not match the fofset', () => {
- it('returns the provided old log', () => {
- const newData = [{ offset: 101, content: [{ text: 'foobar' }] }];
- const result = findOffsetAndRemove(newData, existingLog);
-
- expect(result).toEqual(existingLog);
- });
- });
- });
-
- describe('when last item is nested', () => {
- const existingLog = [
- {
- isHeader: true,
- isClosed: false,
- lines: [{ offset: 101, content: [{ text: 'foobar' }], lineNumber: 2 }],
- line: {
- offset: 10,
- lineNumber: 1,
- section_duration: '10:00',
- },
- },
- ];
-
- describe('and matches the offset', () => {
- it('returns an array with the last nested line item removed', () => {
- const newData = [{ offset: 101, content: [{ text: 'foobar' }] }];
-
- const result = findOffsetAndRemove(newData, existingLog);
- expect(result[0].lines).toEqual([]);
- });
- });
-
- describe('and does not match the offset', () => {
- it('returns the provided old log', () => {
- const newData = [{ offset: 120, content: [{ text: 'foobar' }] }];
-
- const result = findOffsetAndRemove(newData, existingLog);
- expect(result).toEqual(existingLog);
- });
- });
- });
-
- describe('when no data is provided', () => {
- it('returns an empty array', () => {
- const result = findOffsetAndRemove();
- expect(result).toEqual([]);
- });
- });
- });
-
- describe('getIncrementalLineNumber', () => {
- describe('when last line is 0', () => {
- it('returns 1', () => {
- const log = [
- {
- content: [],
- lineNumber: 0,
- },
- ];
-
- expect(getIncrementalLineNumber(log)).toEqual(1);
- });
- });
-
- describe('with unnested line', () => {
- it('returns the lineNumber of the last item in the array', () => {
- const log = [
- {
- content: [],
- lineNumber: 10,
- },
- {
- content: [],
- lineNumber: 101,
- },
- ];
-
- expect(getIncrementalLineNumber(log)).toEqual(102);
- });
- });
-
- describe('when last line is the header section', () => {
- it('returns the lineNumber of the last item in the array', () => {
- const log = [
- {
- content: [],
- lineNumber: 10,
- },
- {
- isHeader: true,
- line: {
- lineNumber: 101,
- content: [],
- },
- lines: [],
- },
- ];
-
- expect(getIncrementalLineNumber(log)).toEqual(102);
- });
- });
-
- describe('when last line is a nested line', () => {
- it('returns the lineNumber of the last item in the nested array', () => {
- const log = [
- {
- content: [],
- lineNumber: 10,
- },
- {
- isHeader: true,
- line: {
- lineNumber: 101,
- content: [],
- },
- lines: [
- {
- lineNumber: 102,
- content: [],
- },
- { lineNumber: 103, content: [] },
- ],
- },
- ];
-
- expect(getIncrementalLineNumber(log)).toEqual(104);
- });
- });
- });
-
- describe('updateIncrementalJobLog', () => {
- describe('without repeated section', () => {
- it('concats and parses both arrays', () => {
- const oldLog = logLinesParser(originalTrace);
- const result = updateIncrementalJobLog(regularIncremental, oldLog);
-
- expect(result).toEqual([
- {
- offset: 1,
- content: [
- {
- text: 'Downloading',
- },
- ],
- lineNumber: 0,
- },
- {
- offset: 2,
- content: [
- {
- text: 'log line',
- },
- ],
- lineNumber: 1,
- },
- ]);
- });
- });
-
- describe('with regular line repeated offset', () => {
- it('updates the last line and formats with the incremental part', () => {
- const oldLog = logLinesParser(originalTrace);
- const result = updateIncrementalJobLog(regularIncrementalRepeated, oldLog);
-
- expect(result).toEqual([
- {
- offset: 1,
- content: [
- {
- text: 'log line',
- },
- ],
- lineNumber: 0,
- },
- ]);
- });
- });
-
- describe('with header line repeated', () => {
- it('updates the header line and formats with the incremental part', () => {
- const oldLog = logLinesParser(headerTrace);
- const result = updateIncrementalJobLog(headerTraceIncremental, oldLog);
-
- expect(result).toEqual([
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- lineNumber: 0,
- },
- lines: [],
- },
- ]);
- });
- });
-
- describe('with collapsible line repeated', () => {
- it('updates the collapsible line and formats with the incremental part', () => {
- const oldLog = logLinesParser(collapsibleTrace);
- const result = updateIncrementalJobLog(collapsibleTraceIncremental, oldLog);
-
- expect(result).toEqual([
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'log line',
- },
- ],
- section: 'section',
- lineNumber: 0,
- },
- lines: [
- {
- offset: 2,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- lineNumber: 1,
- },
- ],
- },
- ]);
- });
- });
- });
-});