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/registry/settings')
-rw-r--r--spec/frontend/registry/settings/components/expiration_dropdown_spec.js83
-rw-r--r--spec/frontend/registry/settings/components/expiration_run_text_spec.js66
-rw-r--r--spec/frontend/registry/settings/components/expiration_textarea_spec.js169
-rw-r--r--spec/frontend/registry/settings/components/expiration_toggle_spec.js80
-rw-r--r--spec/frontend/registry/settings/mock_data.js24
5 files changed, 410 insertions, 12 deletions
diff --git a/spec/frontend/registry/settings/components/expiration_dropdown_spec.js b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js
new file mode 100644
index 00000000000..e0cac317ad6
--- /dev/null
+++ b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js
@@ -0,0 +1,83 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlFormGroup, GlFormSelect } from 'jest/registry/shared/stubs';
+import component from '~/registry/settings/components/expiration_dropdown.vue';
+
+describe('ExpirationDropdown', () => {
+ let wrapper;
+
+ const defaultProps = {
+ name: 'foo',
+ label: 'label-bar',
+ formOptions: [{ key: 'foo', label: 'bar' }, { key: 'baz', label: 'zab' }],
+ };
+
+ const findFormSelect = () => wrapper.find(GlFormSelect);
+ const findFormGroup = () => wrapper.find(GlFormGroup);
+ const findOptions = () => wrapper.findAll('[data-testid="option"]');
+
+ const mountComponent = props => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlFormGroup,
+ GlFormSelect,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('structure', () => {
+ it('has a form-select component', () => {
+ mountComponent();
+ expect(findFormSelect().exists()).toBe(true);
+ });
+
+ it('has the correct options', () => {
+ mountComponent();
+
+ expect(findOptions()).toHaveLength(defaultProps.formOptions.length);
+ });
+ });
+
+ describe('model', () => {
+ it('assign the right props to the form-select component', () => {
+ const value = 'foobar';
+ const disabled = true;
+
+ mountComponent({ value, disabled });
+
+ expect(findFormSelect().props()).toMatchObject({
+ value,
+ disabled,
+ });
+ expect(findFormSelect().attributes('id')).toBe(defaultProps.name);
+ });
+
+ it('assign the right props to the form-group component', () => {
+ mountComponent();
+
+ expect(findFormGroup().attributes()).toMatchObject({
+ id: `${defaultProps.name}-form-group`,
+ 'label-for': defaultProps.name,
+ label: defaultProps.label,
+ });
+ });
+
+ it('emits input event when form-select emits input', () => {
+ const emittedValue = 'barfoo';
+
+ mountComponent();
+
+ findFormSelect().vm.$emit('input', emittedValue);
+
+ expect(wrapper.emitted('input')).toEqual([[emittedValue]]);
+ });
+ });
+});
diff --git a/spec/frontend/registry/settings/components/expiration_run_text_spec.js b/spec/frontend/registry/settings/components/expiration_run_text_spec.js
new file mode 100644
index 00000000000..d023f1fd05a
--- /dev/null
+++ b/spec/frontend/registry/settings/components/expiration_run_text_spec.js
@@ -0,0 +1,66 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlFormInput } from '@gitlab/ui';
+import { GlFormGroup } from 'jest/registry/shared/stubs';
+import component from '~/registry/settings/components/expiration_run_text.vue';
+import { NEXT_CLEANUP_LABEL, NOT_SCHEDULED_POLICY_TEXT } from '~/registry/settings/constants';
+
+describe('ExpirationToggle', () => {
+ let wrapper;
+ const value = 'foo';
+
+ const findInput = () => wrapper.find(GlFormInput);
+ const findFormGroup = () => wrapper.find(GlFormGroup);
+
+ const mountComponent = propsData => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlFormGroup,
+ },
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('structure', () => {
+ it('has an input component', () => {
+ mountComponent();
+ expect(findInput().exists()).toBe(true);
+ });
+ });
+
+ describe('model', () => {
+ it('assigns the right props to the input component', () => {
+ mountComponent({ value, disabled: true });
+
+ expect(findInput().attributes()).toMatchObject({
+ value,
+ });
+ });
+
+ it('assigns the right props to the form-group component', () => {
+ mountComponent();
+
+ expect(findFormGroup().attributes()).toMatchObject({
+ label: NEXT_CLEANUP_LABEL,
+ });
+ });
+ });
+
+ describe('formattedValue', () => {
+ it('displays the values when it exists', () => {
+ mountComponent({ value });
+
+ expect(findInput().attributes('value')).toBe(value);
+ });
+
+ it('displays a placeholder when no value is present', () => {
+ mountComponent();
+
+ expect(findInput().attributes('value')).toBe(NOT_SCHEDULED_POLICY_TEXT);
+ });
+ });
+});
diff --git a/spec/frontend/registry/settings/components/expiration_textarea_spec.js b/spec/frontend/registry/settings/components/expiration_textarea_spec.js
new file mode 100644
index 00000000000..80464c61117
--- /dev/null
+++ b/spec/frontend/registry/settings/components/expiration_textarea_spec.js
@@ -0,0 +1,169 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf, GlFormTextarea, GlLink } from '@gitlab/ui';
+import { GlFormGroup } from 'jest/registry/shared/stubs';
+import component from '~/registry/settings/components/expiration_textarea.vue';
+import { NAME_REGEX_LENGTH } from '~/registry/shared/constants';
+
+describe('ExpirationTextarea', () => {
+ let wrapper;
+
+ const defaultProps = {
+ name: 'foo',
+ label: 'label-bar',
+ placeholder: 'placeholder-baz',
+ description: '%{linkStart}description-foo%{linkEnd}',
+ };
+
+ const tagsRegexHelpPagePath = 'fooPath';
+
+ const findTextArea = () => wrapper.find(GlFormTextarea);
+ const findFormGroup = () => wrapper.find(GlFormGroup);
+ const findLabel = () => wrapper.find('[data-testid="label"]');
+ const findDescription = () => wrapper.find('[data-testid="description"]');
+ const findDescriptionLink = () => wrapper.find(GlLink);
+
+ const mountComponent = props => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlSprintf,
+ GlFormGroup,
+ },
+ provide: {
+ tagsRegexHelpPagePath,
+ },
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('structure', () => {
+ it('has a label', () => {
+ mountComponent();
+
+ expect(findLabel().text()).toBe(defaultProps.label);
+ });
+
+ it('has a textarea component', () => {
+ mountComponent();
+
+ expect(findTextArea().exists()).toBe(true);
+ });
+
+ it('has a description', () => {
+ mountComponent();
+
+ expect(findDescription().text()).toMatchInterpolatedText(defaultProps.description);
+ });
+
+ it('has a description link', () => {
+ mountComponent();
+
+ const link = findDescriptionLink();
+ expect(link.exists()).toBe(true);
+ expect(link.attributes('href')).toBe(tagsRegexHelpPagePath);
+ });
+ });
+
+ describe('model', () => {
+ it('assigns the right props to the textarea component', () => {
+ const value = 'foobar';
+ const disabled = true;
+
+ mountComponent({ value, disabled });
+
+ expect(findTextArea().attributes()).toMatchObject({
+ id: defaultProps.name,
+ value,
+ placeholder: defaultProps.placeholder,
+ disabled: `${disabled}`,
+ trim: '',
+ });
+ });
+
+ it('emits input event when textarea emits input', () => {
+ const emittedValue = 'barfoo';
+
+ mountComponent();
+
+ findTextArea().vm.$emit('input', emittedValue);
+ expect(wrapper.emitted('input')).toEqual([[emittedValue]]);
+ });
+ });
+
+ describe('regex textarea validation', () => {
+ const invalidString = new Array(NAME_REGEX_LENGTH + 2).join(',');
+
+ describe('when error contains an error message', () => {
+ const errorMessage = 'something went wrong';
+
+ it('shows the error message on the relevant field', () => {
+ mountComponent({ error: errorMessage });
+
+ expect(findFormGroup().attributes('invalid-feedback')).toBe(errorMessage);
+ });
+
+ it('gives precedence to API errors compared to local ones', () => {
+ mountComponent({
+ error: errorMessage,
+ value: invalidString,
+ });
+
+ expect(findFormGroup().attributes('invalid-feedback')).toBe(errorMessage);
+ });
+ });
+
+ describe('when error is empty', () => {
+ describe('if the user did not type', () => {
+ it('validation is not emitted', () => {
+ mountComponent();
+
+ expect(wrapper.emitted('validation')).toBeUndefined();
+ });
+
+ it('no error message is shown', () => {
+ mountComponent();
+
+ expect(findFormGroup().props('state')).toBe(true);
+ expect(findFormGroup().attributes('invalid-feedback')).toBe('');
+ });
+ });
+
+ describe('when the user typed something', () => {
+ describe(`when name regex is longer than ${NAME_REGEX_LENGTH}`, () => {
+ beforeEach(() => {
+ // since the component has no state we both emit the event and set the prop
+ mountComponent({ value: invalidString });
+
+ findTextArea().vm.$emit('input', invalidString);
+ });
+
+ it('textAreaValidation state is false', () => {
+ expect(findFormGroup().props('state')).toBe(false);
+ expect(findTextArea().attributes('state')).toBeUndefined();
+ });
+
+ it('emits the @validation event with false payload', () => {
+ expect(wrapper.emitted('validation')).toEqual([[false]]);
+ });
+ });
+
+ it(`when user input is less than ${NAME_REGEX_LENGTH} state is "true"`, () => {
+ mountComponent();
+
+ findTextArea().vm.$emit('input', 'foo');
+
+ expect(findFormGroup().props('state')).toBe(true);
+ expect(findTextArea().attributes('state')).toBe('true');
+ expect(wrapper.emitted('validation')).toEqual([[true]]);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/registry/settings/components/expiration_toggle_spec.js b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
new file mode 100644
index 00000000000..8b670c98dc1
--- /dev/null
+++ b/spec/frontend/registry/settings/components/expiration_toggle_spec.js
@@ -0,0 +1,80 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlToggle, GlSprintf } from '@gitlab/ui';
+import { GlFormGroup } from 'jest/registry/shared/stubs';
+import component from '~/registry/settings/components/expiration_toggle.vue';
+import {
+ ENABLE_TOGGLE_DESCRIPTION,
+ ENABLED_TEXT,
+ DISABLED_TEXT,
+} from '~/registry/settings/constants';
+
+describe('ExpirationToggle', () => {
+ let wrapper;
+
+ const findToggle = () => wrapper.find(GlToggle);
+ const findDescription = () => wrapper.find('[data-testid="description"]');
+
+ const mountComponent = propsData => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlFormGroup,
+ GlSprintf,
+ },
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('structure', () => {
+ it('has a toggle component', () => {
+ mountComponent();
+
+ expect(findToggle().exists()).toBe(true);
+ });
+
+ it('has a description', () => {
+ mountComponent();
+
+ expect(findDescription().text()).toContain(
+ ENABLE_TOGGLE_DESCRIPTION.replace('%{toggleStatus}', ''),
+ );
+ });
+ });
+
+ describe('model', () => {
+ it('assigns the right props to the toggle component', () => {
+ mountComponent({ value: true, disabled: true });
+
+ expect(findToggle().props()).toMatchObject({
+ value: true,
+ disabled: true,
+ });
+ });
+
+ it('emits input event when toggle is updated', () => {
+ mountComponent();
+
+ findToggle().vm.$emit('change', false);
+
+ expect(wrapper.emitted('input')).toEqual([[false]]);
+ });
+ });
+
+ describe('toggle description', () => {
+ it('says enabled when the toggle is on', () => {
+ mountComponent({ value: true });
+
+ expect(findDescription().text()).toContain(ENABLED_TEXT);
+ });
+
+ it('says disabled when the toggle is off', () => {
+ mountComponent({ value: false });
+
+ expect(findDescription().text()).toContain(DISABLED_TEXT);
+ });
+ });
+});
diff --git a/spec/frontend/registry/settings/mock_data.js b/spec/frontend/registry/settings/mock_data.js
index 7f3772ce7fe..7cc645fcf55 100644
--- a/spec/frontend/registry/settings/mock_data.js
+++ b/spec/frontend/registry/settings/mock_data.js
@@ -1,13 +1,18 @@
+export const containerExpirationPolicyData = () => ({
+ cadence: 'EVERY_DAY',
+ enabled: true,
+ keepN: 'TEN_TAGS',
+ nameRegex: 'asdasdssssdfdf',
+ nameRegexKeep: 'sss',
+ olderThan: 'FOURTEEN_DAYS',
+ nextRunAt: '2020-11-19T07:37:03.941Z',
+});
+
export const expirationPolicyPayload = override => ({
data: {
project: {
containerExpirationPolicy: {
- cadence: 'EVERY_DAY',
- enabled: true,
- keepN: 'TEN_TAGS',
- nameRegex: 'asdasdssssdfdf',
- nameRegexKeep: 'sss',
- olderThan: 'FOURTEEN_DAYS',
+ ...containerExpirationPolicyData(),
...override,
},
},
@@ -26,12 +31,7 @@ export const expirationPolicyMutationPayload = ({ override, errors = [] } = {})
data: {
updateContainerExpirationPolicy: {
containerExpirationPolicy: {
- cadence: 'EVERY_DAY',
- enabled: true,
- keepN: 'TEN_TAGS',
- nameRegex: 'asdasdssssdfdf',
- nameRegexKeep: 'sss',
- olderThan: 'FOURTEEN_DAYS',
+ ...containerExpirationPolicyData(),
...override,
},
errors,