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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-28 12:18:08 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-28 12:18:08 +0300
commit70c1d0352e39c3c04caaa3082c3ffb4ad5c29b32 (patch)
treed3ea704848d6a4bb44de46116ee7aec78019e90c /spec/frontend/ci/artifacts/components
parent64a5bf8e84f5f4e3348b1586f3a3904cedceb207 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/ci/artifacts/components')
-rw-r--r--spec/frontend/ci/artifacts/components/artifact_row_spec.js32
-rw-r--r--spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js14
-rw-r--r--spec/frontend/ci/artifacts/components/artifacts_table_row_details_spec.js1
-rw-r--r--spec/frontend/ci/artifacts/components/job_artifacts_table_spec.js51
-rw-r--r--spec/frontend/ci/artifacts/components/job_checkbox_spec.js83
5 files changed, 154 insertions, 27 deletions
diff --git a/spec/frontend/ci/artifacts/components/artifact_row_spec.js b/spec/frontend/ci/artifacts/components/artifact_row_spec.js
index f64d32410ed..ee5d62c2d48 100644
--- a/spec/frontend/ci/artifacts/components/artifact_row_spec.js
+++ b/spec/frontend/ci/artifacts/components/artifact_row_spec.js
@@ -4,7 +4,7 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ArtifactRow from '~/ci/artifacts/components/artifact_row.vue';
-import { BULK_DELETE_FEATURE_FLAG } from '~/ci/artifacts/constants';
+import { BULK_DELETE_FEATURE_FLAG, I18N_BULK_DELETE_MAX_SELECTED } from '~/ci/artifacts/constants';
describe('ArtifactRow component', () => {
let wrapper;
@@ -18,13 +18,15 @@ describe('ArtifactRow component', () => {
const findDeleteButton = () => wrapper.findByTestId('job-artifact-row-delete-button');
const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
- const createComponent = ({ canDestroyArtifacts = true, glFeatures = {} } = {}) => {
+ const createComponent = ({ canDestroyArtifacts = true, glFeatures = {}, props = {} } = {}) => {
wrapper = shallowMountExtended(ArtifactRow, {
propsData: {
artifact,
isSelected: false,
isLoading: false,
isLastRow: false,
+ isSelectedArtifactsLimitReached: false,
+ ...props,
},
provide: { canDestroyArtifacts, glFeatures },
stubs: { GlBadge, GlFriendlyWrap },
@@ -79,15 +81,35 @@ describe('ArtifactRow component', () => {
describe('bulk delete checkbox', () => {
describe('with permission and feature flag enabled', () => {
- beforeEach(() => {
+ it('emits selectArtifact when toggled', () => {
createComponent({ glFeatures: { [BULK_DELETE_FEATURE_FLAG]: true } });
- });
- it('emits selectArtifact when toggled', () => {
findCheckbox().vm.$emit('input', true);
expect(wrapper.emitted('selectArtifact')).toStrictEqual([[artifact, true]]);
});
+
+ describe('when the selected artifacts limit is reached', () => {
+ it('remains enabled if the artifact was selected', () => {
+ createComponent({
+ glFeatures: { [BULK_DELETE_FEATURE_FLAG]: true },
+ props: { isSelected: true, isSelectedArtifactsLimitReached: true },
+ });
+
+ expect(findCheckbox().attributes('disabled')).toBeUndefined();
+ expect(findCheckbox().attributes('title')).toBe('');
+ });
+
+ it('is disabled if the artifact was not selected', () => {
+ createComponent({
+ glFeatures: { [BULK_DELETE_FEATURE_FLAG]: true },
+ props: { isSelected: false, isSelectedArtifactsLimitReached: true },
+ });
+
+ expect(findCheckbox().attributes('disabled')).toBe('true');
+ expect(findCheckbox().attributes('title')).toBe(I18N_BULK_DELETE_MAX_SELECTED);
+ });
+ });
});
it('is not shown without permission', () => {
diff --git a/spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js b/spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js
index 9e4fa6b9c6f..549f6e1e375 100644
--- a/spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js
+++ b/spec/frontend/ci/artifacts/components/artifacts_bulk_delete_spec.js
@@ -1,7 +1,8 @@
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlAlert } from '@gitlab/ui';
import mockGetJobArtifactsResponse from 'test_fixtures/graphql/ci/artifacts/graphql/queries/get_job_artifacts.query.graphql.json';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ArtifactsBulkDelete from '~/ci/artifacts/components/artifacts_bulk_delete.vue';
+import { I18N_BULK_DELETE_MAX_SELECTED } from '~/ci/artifacts/constants';
describe('ArtifactsBulkDelete component', () => {
let wrapper;
@@ -14,11 +15,14 @@ describe('ArtifactsBulkDelete component', () => {
const findText = () => wrapper.findComponent(GlSprintf).text();
const findDeleteButton = () => wrapper.findByTestId('bulk-delete-delete-button');
const findClearButton = () => wrapper.findByTestId('bulk-delete-clear-button');
+ const findAlertText = () => wrapper.findComponent(GlAlert).text();
- const createComponent = () => {
+ const createComponent = (props) => {
wrapper = shallowMountExtended(ArtifactsBulkDelete, {
propsData: {
selectedArtifacts,
+ isSelectedArtifactsLimitReached: false,
+ ...props,
},
stubs: { GlSprintf },
});
@@ -45,4 +49,10 @@ describe('ArtifactsBulkDelete component', () => {
expect(wrapper.emitted('clearSelectedArtifacts')).toBeDefined();
});
});
+
+ it('shows an alert when the selected artifacts limit is reached', () => {
+ createComponent({ isSelectedArtifactsLimitReached: true });
+
+ expect(findAlertText()).toBe(I18N_BULK_DELETE_MAX_SELECTED);
+ });
});
diff --git a/spec/frontend/ci/artifacts/components/artifacts_table_row_details_spec.js b/spec/frontend/ci/artifacts/components/artifacts_table_row_details_spec.js
index ebdb7e25c45..479ecf6b183 100644
--- a/spec/frontend/ci/artifacts/components/artifacts_table_row_details_spec.js
+++ b/spec/frontend/ci/artifacts/components/artifacts_table_row_details_spec.js
@@ -41,6 +41,7 @@ describe('ArtifactsTableRowDetails component', () => {
selectedArtifacts,
refetchArtifacts,
queryVariables: {},
+ isSelectedArtifactsLimitReached: false,
},
provide: { canDestroyArtifacts: true },
data() {
diff --git a/spec/frontend/ci/artifacts/components/job_artifacts_table_spec.js b/spec/frontend/ci/artifacts/components/job_artifacts_table_spec.js
index 74d0d683662..fe58f302a1d 100644
--- a/spec/frontend/ci/artifacts/components/job_artifacts_table_spec.js
+++ b/spec/frontend/ci/artifacts/components/job_artifacts_table_spec.js
@@ -7,7 +7,7 @@ import {
GlModal,
GlFormCheckbox,
} from '@gitlab/ui';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import getJobArtifactsResponse from 'test_fixtures/graphql/ci/artifacts/graphql/queries/get_job_artifacts.query.graphql.json';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -18,6 +18,7 @@ import ArtifactsTableRowDetails from '~/ci/artifacts/components/artifacts_table_
import ArtifactDeleteModal from '~/ci/artifacts/components/artifact_delete_modal.vue';
import ArtifactsBulkDelete from '~/ci/artifacts/components/artifacts_bulk_delete.vue';
import BulkDeleteModal from '~/ci/artifacts/components/bulk_delete_modal.vue';
+import JobCheckbox from '~/ci/artifacts/components/job_checkbox.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import getJobArtifactsQuery from '~/ci/artifacts/graphql/queries/get_job_artifacts.query.graphql';
@@ -31,6 +32,7 @@ import {
INITIAL_CURRENT_PAGE,
BULK_DELETE_FEATURE_FLAG,
I18N_BULK_DELETE_ERROR,
+ SELECTED_ARTIFACTS_MAX_COUNT,
} from '~/ci/artifacts/constants';
import { totalArtifactsSizeForJob } from '~/ci/artifacts/utils';
import { createAlert } from '~/alert';
@@ -123,6 +125,8 @@ describe('JobArtifactsTable component', () => {
},
});
+ const maxSelectedArtifacts = new Array(SELECTED_ARTIFACTS_MAX_COUNT).fill({});
+
const createComponent = ({
handlers = {
getJobArtifactsQuery: jest.fn().mockResolvedValue(getJobArtifactsResponse),
@@ -236,12 +240,12 @@ describe('JobArtifactsTable component', () => {
expect(findDetailsRows().length).toBe(0);
findCount().trigger('click');
- await waitForPromises();
+ await nextTick();
expect(findDetailsRows().length).toBe(1);
findCount().trigger('click');
- await waitForPromises();
+ await nextTick();
expect(findDetailsRows().length).toBe(0);
});
@@ -252,7 +256,7 @@ describe('JobArtifactsTable component', () => {
expect(findDetailsInRow(1).exists()).toBe(false);
findCountAt(0).trigger('click');
- await waitForPromises();
+ await nextTick();
// first job is expanded, second row has its details
expect(findDetailsInRow(0).exists()).toBe(false);
@@ -260,7 +264,7 @@ describe('JobArtifactsTable component', () => {
expect(findDetailsInRow(2).exists()).toBe(false);
findCountAt(1).trigger('click');
- await waitForPromises();
+ await nextTick();
// both jobs are expanded, each has details below it
expect(findDetailsInRow(0).exists()).toBe(false);
@@ -269,7 +273,7 @@ describe('JobArtifactsTable component', () => {
expect(findDetailsInRow(3).exists()).toBe(true);
findCountAt(0).trigger('click');
- await waitForPromises();
+ await nextTick();
// first job collapsed, second job expanded
expect(findDetailsInRow(0).exists()).toBe(false);
@@ -285,7 +289,7 @@ describe('JobArtifactsTable component', () => {
expect(findDetailsInRow(1).exists()).toBe(true);
findArtifactDeleteButton().vm.$emit('click');
- await waitForPromises();
+ await nextTick();
expect(findDeleteModal().findComponent(GlModal).props('visible')).toBe(true);
@@ -510,7 +514,7 @@ describe('JobArtifactsTable component', () => {
findJobCheckbox().vm.$emit('input', true);
findBulkDelete().vm.$emit('showBulkDeleteModal');
- await waitForPromises();
+ await nextTick();
expect(findBulkDeleteModal().props('visible')).toBe(true);
});
@@ -543,6 +547,35 @@ describe('JobArtifactsTable component', () => {
});
});
+ describe('when the selected artifacts limit is reached', () => {
+ beforeEach(async () => {
+ createComponent({
+ canDestroyArtifacts: true,
+ glFeatures: { [BULK_DELETE_FEATURE_FLAG]: true },
+ data: { selectedArtifacts: maxSelectedArtifacts },
+ });
+
+ await nextTick();
+ });
+
+ it('passes isSelectedArtifactsLimitReached to bulk delete', () => {
+ expect(findBulkDelete().props('isSelectedArtifactsLimitReached')).toBe(true);
+ });
+
+ it('passes isSelectedArtifactsLimitReached to job checkbox', () => {
+ expect(wrapper.findComponent(JobCheckbox).props('isSelectedArtifactsLimitReached')).toBe(
+ true,
+ );
+ });
+
+ it('passes isSelectedArtifactsLimitReached to table row details', async () => {
+ findCount().trigger('click');
+ await nextTick();
+
+ expect(findDetailsInRow(1).props('isSelectedArtifactsLimitReached')).toBe(true);
+ });
+ });
+
it('shows an alert and does not clear selected artifacts on error', async () => {
createComponent({
canDestroyArtifacts: true,
@@ -604,7 +637,7 @@ describe('JobArtifactsTable component', () => {
data: { pageInfo },
});
- await waitForPromises();
+ await nextTick();
});
it('renders pagination and passes page props', () => {
diff --git a/spec/frontend/ci/artifacts/components/job_checkbox_spec.js b/spec/frontend/ci/artifacts/components/job_checkbox_spec.js
index ae70bb4b17b..56f1d8cc47b 100644
--- a/spec/frontend/ci/artifacts/components/job_checkbox_spec.js
+++ b/spec/frontend/ci/artifacts/components/job_checkbox_spec.js
@@ -2,6 +2,7 @@ import { GlFormCheckbox } from '@gitlab/ui';
import mockGetJobArtifactsResponse from 'test_fixtures/graphql/ci/artifacts/graphql/queries/get_job_artifacts.query.graphql.json';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import JobCheckbox from '~/ci/artifacts/components/job_checkbox.vue';
+import { I18N_BULK_DELETE_MAX_SELECTED } from '~/ci/artifacts/constants';
describe('JobCheckbox component', () => {
let wrapper;
@@ -16,12 +17,14 @@ describe('JobCheckbox component', () => {
hasArtifacts = true,
selectedArtifacts = mockSelectedArtifacts,
unselectedArtifacts = mockUnselectedArtifacts,
+ isSelectedArtifactsLimitReached = false,
} = {}) => {
wrapper = shallowMountExtended(JobCheckbox, {
propsData: {
hasArtifacts,
selectedArtifacts,
unselectedArtifacts,
+ isSelectedArtifactsLimitReached,
},
mocks: { GlFormCheckbox },
});
@@ -33,24 +36,44 @@ describe('JobCheckbox component', () => {
expect(findCheckbox().attributes('disabled')).toBe('true');
});
- describe('when some artifacts are selected', () => {
- beforeEach(() => {
- createComponent();
- });
+ describe('when some artifacts from this job are selected', () => {
+ describe('when the selected artifacts limit has not been reached', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('is indeterminate', () => {
+ expect(findCheckbox().attributes('indeterminate')).toBe('true');
+ expect(findCheckbox().attributes('checked')).toBeUndefined();
+ });
+
+ it('selects the unselected artifacts on click', () => {
+ findCheckbox().vm.$emit('input', true);
- it('is indeterminate', () => {
- expect(findCheckbox().attributes('indeterminate')).toBe('true');
- expect(findCheckbox().attributes('checked')).toBeUndefined();
+ expect(wrapper.emitted('selectArtifact')).toMatchObject([
+ [mockUnselectedArtifacts[0], true],
+ ]);
+ });
});
- it('selects the unselected artifacts on click', () => {
- findCheckbox().vm.$emit('input', true);
+ describe('when the selected artifacts limit has been reached', () => {
+ beforeEach(() => {
+ // limit has been reached by selecting artifacts from this job
+ createComponent({
+ selectedArtifacts: mockSelectedArtifacts,
+ isSelectedArtifactsLimitReached: true,
+ });
+ });
- expect(wrapper.emitted('selectArtifact')).toMatchObject([[mockUnselectedArtifacts[0], true]]);
+ it('remains enabled', () => {
+ // job checkbox remains enabled to allow de-selection
+ expect(findCheckbox().attributes('disabled')).toBeUndefined();
+ expect(findCheckbox().attributes('title')).not.toBe(I18N_BULK_DELETE_MAX_SELECTED);
+ });
});
});
- describe('when all artifacts are selected', () => {
+ describe('when all artifacts from this job are selected', () => {
beforeEach(() => {
createComponent({ unselectedArtifacts: [] });
});
@@ -68,4 +91,42 @@ describe('JobCheckbox component', () => {
]);
});
});
+
+ describe('when no artifacts from this job are selected', () => {
+ describe('when the selected artifacts limit has not been reached', () => {
+ beforeEach(() => {
+ createComponent({ selectedArtifacts: [] });
+ });
+
+ it('is enabled and not checked', () => {
+ expect(findCheckbox().attributes('checked')).toBeUndefined();
+ expect(findCheckbox().attributes('disabled')).toBeUndefined();
+ expect(findCheckbox().attributes('title')).toBe('');
+ });
+
+ it('selects the artifacts on click', () => {
+ findCheckbox().vm.$emit('input', true);
+
+ expect(wrapper.emitted('selectArtifact')).toMatchObject([
+ [mockUnselectedArtifacts[0], true],
+ ]);
+ });
+ });
+
+ describe('when the selected artifacts limit has been reached', () => {
+ beforeEach(() => {
+ // limit has been reached by selecting artifacts from other jobs
+ createComponent({
+ selectedArtifacts: [],
+ isSelectedArtifactsLimitReached: true,
+ });
+ });
+
+ it('is disabled when the selected artifacts limit has been reached', () => {
+ // job checkbox is disabled to block further selection
+ expect(findCheckbox().attributes('disabled')).toBe('true');
+ expect(findCheckbox().attributes('title')).toBe(I18N_BULK_DELETE_MAX_SELECTED);
+ });
+ });
+ });
});