Commit 2520e00b authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera Committed by Natalia Tepluhina

Rename model fields

- expiration_policy_fields
- tests
parent cef17004
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import { isEqual } from 'lodash';
import expirationPolicyQuery from '../graphql/queries/get_expiration_policy.graphql';
import { FETCH_SETTINGS_ERROR_MESSAGE } from '../../shared/constants'; import { FETCH_SETTINGS_ERROR_MESSAGE } from '../../shared/constants';
import SettingsForm from './settings_form.vue'; import SettingsForm from './settings_form.vue';
...@@ -19,21 +19,39 @@ export default { ...@@ -19,21 +19,39 @@ export default {
GlSprintf, GlSprintf,
GlLink, GlLink,
}, },
inject: ['projectPath', 'isAdmin', 'adminSettingsPath', 'enableHistoricEntries'],
i18n: { i18n: {
UNAVAILABLE_FEATURE_TITLE, UNAVAILABLE_FEATURE_TITLE,
UNAVAILABLE_FEATURE_INTRO_TEXT, UNAVAILABLE_FEATURE_INTRO_TEXT,
FETCH_SETTINGS_ERROR_MESSAGE, FETCH_SETTINGS_ERROR_MESSAGE,
}, },
apollo: {
containerExpirationPolicy: {
query: expirationPolicyQuery,
variables() {
return {
projectPath: this.projectPath,
};
},
update: data => data.project?.containerExpirationPolicy,
result({ data }) {
this.workingCopy = { ...data.project?.containerExpirationPolicy };
},
error(e) {
this.fetchSettingsError = e;
},
},
},
data() { data() {
return { return {
fetchSettingsError: false, fetchSettingsError: false,
containerExpirationPolicy: null,
workingCopy: {},
}; };
}, },
computed: { computed: {
...mapState(['isAdmin', 'adminSettingsPath']), isDisabled() {
...mapGetters({ isDisabled: 'getIsDisabled' }), return !(this.containerExpirationPolicy || this.enableHistoricEntries);
showSettingForm() {
return !this.isDisabled && !this.fetchSettingsError;
}, },
showDisabledFormMessage() { showDisabledFormMessage() {
return this.isDisabled && !this.fetchSettingsError; return this.isDisabled && !this.fetchSettingsError;
...@@ -41,21 +59,27 @@ export default { ...@@ -41,21 +59,27 @@ export default {
unavailableFeatureMessage() { unavailableFeatureMessage() {
return this.isAdmin ? UNAVAILABLE_ADMIN_FEATURE_TEXT : UNAVAILABLE_USER_FEATURE_TEXT; return this.isAdmin ? UNAVAILABLE_ADMIN_FEATURE_TEXT : UNAVAILABLE_USER_FEATURE_TEXT;
}, },
isEdited() {
return !isEqual(this.containerExpirationPolicy, this.workingCopy);
}, },
mounted() {
this.fetchSettings().catch(() => {
this.fetchSettingsError = true;
});
}, },
methods: { methods: {
...mapActions(['fetchSettings']), restoreOriginal() {
this.workingCopy = { ...this.containerExpirationPolicy };
},
}, },
}; };
</script> </script>
<template> <template>
<div> <div>
<settings-form v-if="showSettingForm" /> <settings-form
v-if="containerExpirationPolicy"
v-model="workingCopy"
:is-loading="$apollo.queries.containerExpirationPolicy.loading"
:is-edited="isEdited"
@reset="restoreOriginal"
/>
<template v-else> <template v-else>
<gl-alert <gl-alert
v-if="showDisabledFormMessage" v-if="showDisabledFormMessage"
......
<script> <script>
import { get } from 'lodash'; import { GlCard, GlButton } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlCard, GlButton, GlLoadingIcon } from '@gitlab/ui';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { mapComputed } from '~/vuex_shared/bindings';
import { import {
UPDATE_SETTINGS_ERROR_MESSAGE, UPDATE_SETTINGS_ERROR_MESSAGE,
UPDATE_SETTINGS_SUCCESS_MESSAGE, UPDATE_SETTINGS_SUCCESS_MESSAGE,
} from '../../shared/constants'; } from '../../shared/constants';
import ExpirationPolicyFields from '../../shared/components/expiration_policy_fields.vue'; import ExpirationPolicyFields from '../../shared/components/expiration_policy_fields.vue';
import { SET_CLEANUP_POLICY_BUTTON, CLEANUP_POLICY_CARD_HEADER } from '../constants'; import { SET_CLEANUP_POLICY_BUTTON, CLEANUP_POLICY_CARD_HEADER } from '../constants';
import { formOptionsGenerator } from '~/registry/shared/utils';
import updateContainerExpirationPolicyMutation from '../graphql/mutations/update_container_expiration_policy.graphql';
import { updateContainerExpirationPolicy } from '../graphql/utils/cache_update';
export default { export default {
components: { components: {
GlCard, GlCard,
GlButton, GlButton,
GlLoadingIcon,
ExpirationPolicyFields, ExpirationPolicyFields,
}, },
mixins: [Tracking.mixin()], mixins: [Tracking.mixin()],
inject: ['projectPath'],
props: {
value: {
type: Object,
required: true,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
isEdited: {
type: Boolean,
required: false,
default: false,
},
},
labelsConfig: { labelsConfig: {
cols: 3, cols: 3,
align: 'right', align: 'right',
}, },
formOptions: formOptionsGenerator(),
i18n: { i18n: {
CLEANUP_POLICY_CARD_HEADER, CLEANUP_POLICY_CARD_HEADER,
SET_CLEANUP_POLICY_BUTTON, SET_CLEANUP_POLICY_BUTTON,
...@@ -34,49 +51,74 @@ export default { ...@@ -34,49 +51,74 @@ export default {
}, },
fieldsAreValid: true, fieldsAreValid: true,
apiErrors: null, apiErrors: null,
mutationLoading: false,
}; };
}, },
computed: { computed: {
...mapState(['formOptions', 'isLoading']), showLoadingIcon() {
...mapGetters({ isEdited: 'getIsEdited' }), return this.isLoading || this.mutationLoading;
...mapComputed([{ key: 'settings', getter: 'getSettings' }], 'updateSettings'), },
isSubmitButtonDisabled() { isSubmitButtonDisabled() {
return !this.fieldsAreValid || this.isLoading; return !this.fieldsAreValid || this.showLoadingIcon;
}, },
isCancelButtonDisabled() { isCancelButtonDisabled() {
return !this.isEdited || this.isLoading; return !this.isEdited || this.isLoading || this.mutationLoading;
},
mutationVariables() {
return {
projectPath: this.projectPath,
enabled: this.value.enabled,
cadence: this.value.cadence,
olderThan: this.value.olderThan,
keepN: this.value.keepN,
nameRegex: this.value.nameRegex,
nameRegexKeep: this.value.nameRegexKeep,
};
}, },
}, },
methods: { methods: {
...mapActions(['resetSettings', 'saveSettings']),
reset() { reset() {
this.track('reset_form'); this.track('reset_form');
this.apiErrors = null; this.apiErrors = null;
this.resetSettings(); this.$emit('reset');
}, },
setApiErrors(response) { setApiErrors(response) {
const messages = get(response, 'data.message', []); this.apiErrors = response.graphQLErrors.reduce((acc, curr) => {
curr.extensions.problems.forEach(item => {
this.apiErrors = Object.keys(messages).reduce((acc, curr) => { acc[item.path[0]] = item.message;
if (curr.startsWith('container_expiration_policy.')) { });
const key = curr.replace('container_expiration_policy.', '');
acc[key] = get(messages, [curr, 0], '');
}
return acc; return acc;
}, {}); }, {});
}, },
submit() { submit() {
this.track('submit_form'); this.track('submit_form');
this.apiErrors = null; this.apiErrors = null;
this.saveSettings() this.mutationLoading = true;
.then(() => this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' })) return this.$apollo
.catch(({ response }) => { .mutate({
this.setApiErrors(response); mutation: updateContainerExpirationPolicyMutation,
variables: {
input: this.mutationVariables,
},
update: updateContainerExpirationPolicy(this.projectPath),
})
.then(({ data }) => {
const errorMessage = data?.updateContainerExpirationPolicy?.errors[0];
if (errorMessage) {
this.$toast.show(errorMessage, { type: 'error' });
}
this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' });
})
.catch(error => {
this.setApiErrors(error);
this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE, { type: 'error' }); this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE, { type: 'error' });
})
.finally(() => {
this.mutationLoading = false;
}); });
}, },
onModelChange(changePayload) { onModelChange(changePayload) {
this.settings = changePayload.newValue; this.$emit('input', changePayload.newValue);
if (this.apiErrors) { if (this.apiErrors) {
this.apiErrors[changePayload.modified] = undefined; this.apiErrors[changePayload.modified] = undefined;
} }
...@@ -93,8 +135,8 @@ export default { ...@@ -93,8 +135,8 @@ export default {
</template> </template>
<template #default> <template #default>
<expiration-policy-fields <expiration-policy-fields
:value="settings" :value="value"
:form-options="formOptions" :form-options="$options.formOptions"
:is-loading="isLoading" :is-loading="isLoading"
:api-errors="apiErrors" :api-errors="apiErrors"
@validated="fieldsAreValid = true" @validated="fieldsAreValid = true"
...@@ -115,12 +157,12 @@ export default { ...@@ -115,12 +157,12 @@ export default {
ref="save-button" ref="save-button"
type="submit" type="submit"
:disabled="isSubmitButtonDisabled" :disabled="isSubmitButtonDisabled"
:loading="showLoadingIcon"
variant="success" variant="success"
category="primary" category="primary"
class="js-no-auto-disable" class="js-no-auto-disable"
> >
{{ $options.i18n.SET_CLEANUP_POLICY_BUTTON }} {{ $options.i18n.SET_CLEANUP_POLICY_BUTTON }}
<gl-loading-icon v-if="isLoading" class="gl-ml-3" />
</gl-button> </gl-button>
</template> </template>
</gl-card> </gl-card>
......
...@@ -68,34 +68,31 @@ export default { ...@@ -68,34 +68,31 @@ export default {
{ {
name: 'expiration-policy-interval', name: 'expiration-policy-interval',
label: EXPIRATION_INTERVAL_LABEL, label: EXPIRATION_INTERVAL_LABEL,
model: 'older_than', model: 'olderThan',
optionKey: 'olderThan',
}, },
{ {
name: 'expiration-policy-schedule', name: 'expiration-policy-schedule',
label: EXPIRATION_SCHEDULE_LABEL, label: EXPIRATION_SCHEDULE_LABEL,
model: 'cadence', model: 'cadence',
optionKey: 'cadence',
}, },
{ {
name: 'expiration-policy-latest', name: 'expiration-policy-latest',
label: KEEP_N_LABEL, label: KEEP_N_LABEL,
model: 'keep_n', model: 'keepN',
optionKey: 'keepN',
}, },
], ],
textAreaList: [ textAreaList: [
{ {
name: 'expiration-policy-name-matching', name: 'expiration-policy-name-matching',
label: NAME_REGEX_LABEL, label: NAME_REGEX_LABEL,
model: 'name_regex', model: 'nameRegex',
placeholder: NAME_REGEX_PLACEHOLDER, placeholder: NAME_REGEX_PLACEHOLDER,
description: NAME_REGEX_DESCRIPTION, description: NAME_REGEX_DESCRIPTION,
}, },
{ {
name: 'expiration-policy-keep-name', name: 'expiration-policy-keep-name',
label: NAME_REGEX_KEEP_LABEL, label: NAME_REGEX_KEEP_LABEL,
model: 'name_regex_keep', model: 'nameRegexKeep',
placeholder: NAME_REGEX_KEEP_PLACEHOLDER, placeholder: NAME_REGEX_KEEP_PLACEHOLDER,
description: NAME_REGEX_KEEP_DESCRIPTION, description: NAME_REGEX_KEEP_DESCRIPTION,
}, },
...@@ -107,17 +104,16 @@ export default { ...@@ -107,17 +104,16 @@ export default {
}, },
computed: { computed: {
...mapComputedToEvent( ...mapComputedToEvent(
['enabled', 'cadence', 'older_than', 'keep_n', 'name_regex', 'name_regex_keep'], ['enabled', 'cadence', 'olderThan', 'keepN', 'nameRegex', 'nameRegexKeep'],
'value', 'value',
), ),
policyEnabledText() { policyEnabledText() {
return this.enabled ? ENABLED_TEXT : DISABLED_TEXT; return this.enabled ? ENABLED_TEXT : DISABLED_TEXT;
}, },
textAreaValidation() { textAreaValidation() {
const nameRegexErrors = const nameRegexErrors = this.apiErrors?.nameRegex || this.validateRegexLength(this.nameRegex);
this.apiErrors?.name_regex || this.validateRegexLength(this.name_regex);
const nameKeepRegexErrors = const nameKeepRegexErrors =
this.apiErrors?.name_regex_keep || this.validateRegexLength(this.name_regex_keep); this.apiErrors?.nameRegexKeep || this.validateRegexLength(this.nameRegexKeep);
return { return {
/* /*
...@@ -127,11 +123,11 @@ export default { ...@@ -127,11 +123,11 @@ export default {
* false: red border, error message * false: red border, error message
* So in this function we keep null if the are no message otherwise we 'invert' the error message * So in this function we keep null if the are no message otherwise we 'invert' the error message
*/ */
name_regex: { nameRegex: {
state: nameRegexErrors === null ? null : !nameRegexErrors, state: nameRegexErrors === null ? null : !nameRegexErrors,
message: nameRegexErrors, message: nameRegexErrors,
}, },
name_regex_keep: { nameRegexKeep: {
state: nameKeepRegexErrors === null ? null : !nameKeepRegexErrors, state: nameKeepRegexErrors === null ? null : !nameKeepRegexErrors,
message: nameKeepRegexErrors, message: nameKeepRegexErrors,
}, },
...@@ -139,8 +135,8 @@ export default { ...@@ -139,8 +135,8 @@ export default {
}, },
fieldsValidity() { fieldsValidity() {
return ( return (
this.textAreaValidation.name_regex.state !== false && this.textAreaValidation.nameRegex.state !== false &&
this.textAreaValidation.name_regex_keep.state !== false this.textAreaValidation.nameRegexKeep.state !== false
); );
}, },
isFormElementDisabled() { isFormElementDisabled() {
...@@ -216,11 +212,7 @@ export default { ...@@ -216,11 +212,7 @@ export default {
:disabled="isFormElementDisabled" :disabled="isFormElementDisabled"
@input="updateModel($event, select.model)" @input="updateModel($event, select.model)"
> >
<option <option v-for="option in formOptions[select.model]" :key="option.key" :value="option.key">
v-for="option in formOptions[select.optionKey]"
:key="option.key"
:value="option.key"
>
{{ option.label }} {{ option.label }}
</option> </option>
</gl-form-select> </gl-form-select>
......
...@@ -21,20 +21,26 @@ export const mapComputedToEvent = (list, root) => { ...@@ -21,20 +21,26 @@ export const mapComputedToEvent = (list, root) => {
return result; return result;
}; };
export const optionLabelGenerator = (collection, singularSentence, pluralSentence) => export const olderThanTranslationGenerator = variable =>
n__(
'%d day until tags are automatically removed',
'%d days until tags are automatically removed',
variable,
);
export const keepNTranslationGenerator = variable =>
n__('%d tag per image name', '%d tags per image name', variable);
export const optionLabelGenerator = (collection, translationFn) =>
collection.map(option => ({ collection.map(option => ({
...option, ...option,
label: n__(singularSentence, pluralSentence, option.variable), label: translationFn(option.variable),
})); }));
export const formOptionsGenerator = () => { export const formOptionsGenerator = () => {
return { return {
olderThan: optionLabelGenerator( olderThan: optionLabelGenerator(OLDER_THAN_OPTIONS, olderThanTranslationGenerator),
OLDER_THAN_OPTIONS,
'%d days until tags are automatically removed',
'%d day until tags are automatically removed',
),
cadence: CADENCE_OPTIONS, cadence: CADENCE_OPTIONS,
keepN: optionLabelGenerator(KEEP_N_OPTIONS, '%d tag per image name', '%d tags per image name'), keepN: optionLabelGenerator(KEEP_N_OPTIONS, keepNTranslationGenerator),
}; };
}; };
...@@ -165,6 +165,11 @@ msgid_plural "%d days" ...@@ -165,6 +165,11 @@ msgid_plural "%d days"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%d day until tags are automatically removed"
msgid_plural "%d days until tags are automatically removed"
msgstr[0] ""
msgstr[1] ""
msgid "%d error" msgid "%d error"
msgid_plural "%d errors" msgid_plural "%d errors"
msgstr[0] "" msgstr[0] ""
...@@ -300,6 +305,11 @@ msgid_plural "%d tags" ...@@ -300,6 +305,11 @@ msgid_plural "%d tags"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
msgstr[0] ""
msgstr[1] ""
msgid "%d unassigned issue" msgid "%d unassigned issue"
msgid_plural "%d unassigned issues" msgid_plural "%d unassigned issues"
msgstr[0] "" msgstr[0] ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Registry Settings App renders 1`] = `
<div>
<settings-form-stub />
</div>
`;
import { shallowMount } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import component from '~/registry/settings/components/registry_settings_app.vue'; import component from '~/registry/settings/components/registry_settings_app.vue';
import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.graphql';
import SettingsForm from '~/registry/settings/components/settings_form.vue'; import SettingsForm from '~/registry/settings/components/settings_form.vue';
import { createStore } from '~/registry/settings/store/';
import { SET_SETTINGS, SET_INITIAL_STATE } from '~/registry/settings/store/mutation_types';
import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/shared/constants'; import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/shared/constants';
import { import {
UNAVAILABLE_FEATURE_INTRO_TEXT, UNAVAILABLE_FEATURE_INTRO_TEXT,
UNAVAILABLE_USER_FEATURE_TEXT, UNAVAILABLE_USER_FEATURE_TEXT,
} from '~/registry/settings/constants'; } from '~/registry/settings/constants';
import { stringifiedFormOptions } from '../../shared/mock_data'; import { expirationPolicyPayload } from '../mock_data';
const localVue = createLocalVue();
describe('Registry Settings App', () => { describe('Registry Settings App', () => {
let wrapper; let wrapper;
let store; let fakeApollo;
const defaultProvidedValues = {
projectPath: 'path',
isAdmin: false,
adminSettingsPath: 'settingsPath',
enableHistoricEntries: false,
};
const findSettingsComponent = () => wrapper.find(SettingsForm); const findSettingsComponent = () => wrapper.find(SettingsForm);
const findAlert = () => wrapper.find(GlAlert); const findAlert = () => wrapper.find(GlAlert);
const mountComponent = ({ dispatchMock = 'mockResolvedValue' } = {}) => { const mountComponent = (provide = defaultProvidedValues, config) => {
const dispatchSpy = jest.spyOn(store, 'dispatch');
dispatchSpy[dispatchMock]();
wrapper = shallowMount(component, { wrapper = shallowMount(component, {
stubs: { stubs: {
GlSprintf, GlSprintf,
...@@ -32,71 +39,72 @@ describe('Registry Settings App', () => { ...@@ -32,71 +39,72 @@ describe('Registry Settings App', () => {
show: jest.fn(), show: jest.fn(),
}, },
}, },
store, provide,
...config,
}); });
}; };
beforeEach(() => { const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => {
store = createStore(); localVue.use(VueApollo);
const requestHandlers = [[expirationPolicyQuery, resolver]];
fakeApollo = createMockApollo(requestHandlers);
mountComponent(provide, {
localVue,
apolloProvider: fakeApollo,
}); });
return requestHandlers.map(request => request[1]);
};
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders', () => { it('renders the setting form', async () => {
store.commit(SET_SETTINGS, { foo: 'bar' }); const requests = mountComponentWithApollo({
mountComponent(); resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()),
expect(wrapper.element).toMatchSnapshot();
});
it('call the store function to load the data on mount', () => {
mountComponent();
expect(store.dispatch).toHaveBeenCalledWith('fetchSettings');
}); });
await Promise.all(requests);
it('renders the setting form', () => {
store.commit(SET_SETTINGS, { foo: 'bar' });
mountComponent();
expect(findSettingsComponent().exists()).toBe(true); expect(findSettingsComponent().exists()).toBe(true);
}); });
describe('the form is disabled', () => { describe('the form is disabled', () => {
beforeEach(() => { it('the form is hidden', () => {
store.commit(SET_SETTINGS, undefined);
mountComponent(); mountComponent();
});
it('the form is hidden', () => {
expect(findSettingsComponent().exists()).toBe(false); expect(findSettingsComponent().exists()).toBe(false);
}); });
it('shows an alert', () => { it('shows an alert', () => {
mountComponent();
const text = findAlert().text(); const text = findAlert().text();
expect(text).toContain(UNAVAILABLE_FEATURE_INTRO_TEXT); expect(text).toContain(UNAVAILABLE_FEATURE_INTRO_TEXT);
expect(text).toContain(UNAVAILABLE_USER_FEATURE_TEXT); expect(text).toContain(UNAVAILABLE_USER_FEATURE_TEXT);
}); });
describe('an admin is visiting the page', () => { describe('an admin is visiting the page', () => {
beforeEach(() => {
store.commit(SET_INITIAL_STATE, {
...stringifiedFormOptions,
isAdmin: true,
adminSettingsPath: 'foo',
});
});
it('shows the admin part of the alert message', () => { it('shows the admin part of the alert message', () => {
mountComponent({ ...defaultProvidedValues, isAdmin: true });
const sprintf = findAlert().find(GlSprintf); const sprintf = findAlert().find(GlSprintf);
expect(sprintf.text()).toBe('administration settings'); expect(sprintf.text()).toBe('administration settings');
expect(sprintf.find(GlLink).attributes('href')).toBe('foo'); expect(sprintf.find(GlLink).attributes('href')).toBe(
defaultProvidedValues.adminSettingsPath,
);
}); });
}); });
}); });
describe('fetchSettingsError', () => { describe('fetchSettingsError', () => {
beforeEach(() => { beforeEach(() => {
mountComponent({ dispatchMock: 'mockRejectedValue' }); const requests = mountComponentWithApollo({
resolver: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
return Promise.all(requests);
}); });
it('the form is hidden', () => { it('the form is hidden', () => {
......
export const expirationPolicyPayload = override => ({
data: {
project: {
containerExpirationPolicy: {
cadence: 'EVERY_DAY',
enabled: true,
keepN: 'TEN_TAGS',
nameRegex: 'asdasdssssdfdf',
nameRegexKeep: 'sss',
olderThan: 'FOURTEEN_DAYS',
...override,
},
},
},
});
export const expirationPolicyMutationPayload = ({ override, errors = [] } = {}) => ({
data: {
updateContainerExpirationPolicy: {
containerExpirationPolicy: {
cadence: 'EVERY_DAY',
enabled: true,
keepN: 'TEN_TAGS',
nameRegex: 'asdasdssssdfdf',
nameRegexKeep: 'sss',
olderThan: 'FOURTEEN_DAYS',
...override,
},
errors,
},
},
});
...@@ -76,25 +76,25 @@ Array [ ...@@ -76,25 +76,25 @@ Array [
Object { Object {
"default": false, "default": false,
"key": "SEVEN_DAYS", "key": "SEVEN_DAYS",
"label": "7 day until tags are automatically removed", "label": "7 days until tags are automatically removed",
"variable": 7, "variable": 7,
}, },
Object { Object {
"default": false, "default": false,
"key": "FOURTEEN_DAYS", "key": "FOURTEEN_DAYS",
"label": "14 day until tags are automatically removed", "label": "14 days until tags are automatically removed",
"variable": 14, "variable": 14,
}, },
Object { Object {
"default": false, "default": false,
"key": "THIRTY_DAYS", "key": "THIRTY_DAYS",
"label": "30 day until tags are automatically removed", "label": "30 days until tags are automatically removed",
"variable": 30, "variable": 30,
}, },
Object { Object {
"default": true, "default": true,
"key": "NINETY_DAYS", "key": "NINETY_DAYS",
"label": "90 day until tags are automatically removed", "label": "90 days until tags are automatically removed",
"variable": 90, "variable": 90,
}, },
] ]
......
...@@ -42,11 +42,11 @@ describe('Expiration Policy Form', () => { ...@@ -42,11 +42,11 @@ describe('Expiration Policy Form', () => {
describe.each` describe.each`
elementName | modelName | value | disabledByToggle elementName | modelName | value | disabledByToggle
${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'} ${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'}
${'interval'} | ${'older_than'} | ${'foo'} | ${'disabled'} ${'interval'} | ${'olderThan'} | ${'foo'} | ${'disabled'}
${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'} ${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'}
${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'} ${'latest'} | ${'keepN'} | ${'foo'} | ${'disabled'}
${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'} ${'name-matching'} | ${'nameRegex'} | ${'foo'} | ${'disabled'}
${'keep-name'} | ${'name_regex_keep'} | ${'bar'} | ${'disabled'} ${'keep-name'} | ${'nameRegexKeep'} | ${'bar'} | ${'disabled'}
`( `(
`${FORM_ELEMENTS_ID_PREFIX}-$elementName form element`, `${FORM_ELEMENTS_ID_PREFIX}-$elementName form element`,
({ elementName, modelName, value, disabledByToggle }) => { ({ elementName, modelName, value, disabledByToggle }) => {
...@@ -129,8 +129,8 @@ describe('Expiration Policy Form', () => { ...@@ -129,8 +129,8 @@ describe('Expiration Policy Form', () => {
describe.each` describe.each`
modelName | elementName modelName | elementName
${'name_regex'} | ${'name-matching'} ${'nameRegex'} | ${'name-matching'}
${'name_regex_keep'} | ${'keep-name'} ${'nameRegexKeep'} | ${'keep-name'}
`('regex textarea validation', ({ modelName, elementName }) => { `('regex textarea validation', ({ modelName, elementName }) => {
const invalidString = new Array(NAME_REGEX_LENGTH + 2).join(','); const invalidString = new Array(NAME_REGEX_LENGTH + 2).join(',');
......
export const GlLoadingIcon = { name: 'gl-loading-icon-stub', template: '<svg></svg>' };
export const GlCard = {
name: 'gl-card-stub',
template: `
<div>
<slot name="header"></slot>
<slot></slot>
<slot name="footer"></slot>
</div>
`,
};
import { formOptionsGenerator, optionLabelGenerator } from '~/registry/shared/utils'; import {
formOptionsGenerator,
optionLabelGenerator,
olderThanTranslationGenerator,
} from '~/registry/shared/utils';
describe('Utils', () => { describe('Utils', () => {
describe('optionLabelGenerator', () => { describe('optionLabelGenerator', () => {
it('returns an array with a set label', () => { it('returns an array with a set label', () => {
const result = optionLabelGenerator([{ variable: 1 }, { variable: 2 }], '%d day', '%d days'); const result = optionLabelGenerator(
expect(result).toEqual([{ variable: 1, label: '1 day' }, { variable: 2, label: '2 days' }]); [{ variable: 1 }, { variable: 2 }],
olderThanTranslationGenerator,
);
expect(result).toEqual([
{ variable: 1, label: '1 day until tags are automatically removed' },
{ variable: 2, label: '2 days until tags are automatically removed' },
]);
}); });
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment