diff options
Diffstat (limited to 'spec/frontend/registry/settings')
11 files changed, 0 insertions, 1316 deletions
diff --git a/spec/frontend/registry/settings/__snapshots__/utils_spec.js.snap b/spec/frontend/registry/settings/__snapshots__/utils_spec.js.snap deleted file mode 100644 index 7062773b46b..00000000000 --- a/spec/frontend/registry/settings/__snapshots__/utils_spec.js.snap +++ /dev/null @@ -1,101 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Utils formOptionsGenerator returns an object containing cadence 1`] = ` -Array [ - Object { - "default": true, - "key": "EVERY_DAY", - "label": "Every day", - }, - Object { - "default": false, - "key": "EVERY_WEEK", - "label": "Every week", - }, - Object { - "default": false, - "key": "EVERY_TWO_WEEKS", - "label": "Every two weeks", - }, - Object { - "default": false, - "key": "EVERY_MONTH", - "label": "Every month", - }, - Object { - "default": false, - "key": "EVERY_THREE_MONTHS", - "label": "Every three months", - }, -] -`; - -exports[`Utils formOptionsGenerator returns an object containing keepN 1`] = ` -Array [ - Object { - "default": false, - "key": "ONE_TAG", - "label": "1 tag per image name", - "variable": 1, - }, - Object { - "default": false, - "key": "FIVE_TAGS", - "label": "5 tags per image name", - "variable": 5, - }, - Object { - "default": true, - "key": "TEN_TAGS", - "label": "10 tags per image name", - "variable": 10, - }, - Object { - "default": false, - "key": "TWENTY_FIVE_TAGS", - "label": "25 tags per image name", - "variable": 25, - }, - Object { - "default": false, - "key": "FIFTY_TAGS", - "label": "50 tags per image name", - "variable": 50, - }, - Object { - "default": false, - "key": "ONE_HUNDRED_TAGS", - "label": "100 tags per image name", - "variable": 100, - }, -] -`; - -exports[`Utils formOptionsGenerator returns an object containing olderThan 1`] = ` -Array [ - Object { - "default": false, - "key": "SEVEN_DAYS", - "label": "7 days", - "variable": 7, - }, - Object { - "default": false, - "key": "FOURTEEN_DAYS", - "label": "14 days", - "variable": 14, - }, - Object { - "default": false, - "key": "THIRTY_DAYS", - "label": "30 days", - "variable": 30, - }, - Object { - "default": true, - "key": "NINETY_DAYS", - "label": "90 days", - "variable": 90, - }, -] -`; diff --git a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap deleted file mode 100644 index 7a52b4a5d0f..00000000000 --- a/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap +++ /dev/null @@ -1,64 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Settings Form Cadence matches snapshot 1`] = ` -<expiration-dropdown-stub - class="gl-mr-7 gl-mb-0!" - data-testid="cadence-dropdown" - formoptions="[object Object],[object Object],[object Object],[object Object],[object Object]" - label="Run cleanup:" - name="cadence" - value="EVERY_DAY" -/> -`; - -exports[`Settings Form Enable matches snapshot 1`] = ` -<expiration-toggle-stub - class="gl-mb-0!" - data-testid="enable-toggle" - value="true" -/> -`; - -exports[`Settings Form Keep N matches snapshot 1`] = ` -<expiration-dropdown-stub - data-testid="keep-n-dropdown" - formoptions="[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]" - label="Keep the most recent:" - name="keep-n" - value="TEN_TAGS" -/> -`; - -exports[`Settings Form Keep Regex matches snapshot 1`] = ` -<expiration-input-stub - data-testid="keep-regex-input" - description="Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}" - error="" - label="Keep tags matching:" - name="keep-regex" - placeholder="" - value="sss" -/> -`; - -exports[`Settings Form OlderThan matches snapshot 1`] = ` -<expiration-dropdown-stub - data-testid="older-than-dropdown" - formoptions="[object Object],[object Object],[object Object],[object Object]" - label="Remove tags older than:" - name="older-than" - value="FOURTEEN_DAYS" -/> -`; - -exports[`Settings Form Remove regex matches snapshot 1`] = ` -<expiration-input-stub - data-testid="remove-regex-input" - description="Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}" - error="" - label="Remove tags matching:" - name="remove-regex" - placeholder=".*" - value="asdasdssssdfdf" -/> -`; diff --git a/spec/frontend/registry/settings/components/expiration_dropdown_spec.js b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js deleted file mode 100644 index f777f7ec9de..00000000000 --- a/spec/frontend/registry/settings/components/expiration_dropdown_spec.js +++ /dev/null @@ -1,86 +0,0 @@ -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_input_spec.js b/spec/frontend/registry/settings/components/expiration_input_spec.js deleted file mode 100644 index b91599a2789..00000000000 --- a/spec/frontend/registry/settings/components/expiration_input_spec.js +++ /dev/null @@ -1,169 +0,0 @@ -import { GlSprintf, GlFormInput, GlLink } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { GlFormGroup } from 'jest/registry/shared/stubs'; -import component from '~/registry/settings/components/expiration_input.vue'; -import { NAME_REGEX_LENGTH } from '~/registry/settings/constants'; - -describe('ExpirationInput', () => { - let wrapper; - - const defaultProps = { - name: 'foo', - label: 'label-bar', - placeholder: 'placeholder-baz', - description: '%{linkStart}description-foo%{linkEnd}', - }; - - const tagsRegexHelpPagePath = 'fooPath'; - - const findInput = () => wrapper.find(GlFormInput); - 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(findInput().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(findInput().attributes()).toMatchObject({ - id: defaultProps.name, - value, - placeholder: defaultProps.placeholder, - disabled: `${disabled}`, - trim: '', - }); - }); - - it('emits input event when textarea emits input', () => { - const emittedValue = 'barfoo'; - - mountComponent(); - - findInput().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 }); - - findInput().vm.$emit('input', invalidString); - }); - - it('textAreaValidation state is false', () => { - expect(findFormGroup().props('state')).toBe(false); - expect(findInput().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(); - - findInput().vm.$emit('input', 'foo'); - - expect(findFormGroup().props('state')).toBe(true); - expect(findInput().attributes('state')).toBe('true'); - expect(wrapper.emitted('validation')).toEqual([[true]]); - }); - }); - }); - }); -}); diff --git a/spec/frontend/registry/settings/components/expiration_run_text_spec.js b/spec/frontend/registry/settings/components/expiration_run_text_spec.js deleted file mode 100644 index 753bb10ad08..00000000000 --- a/spec/frontend/registry/settings/components/expiration_run_text_spec.js +++ /dev/null @@ -1,62 +0,0 @@ -import { GlFormInput } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -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 form-group component', () => { - mountComponent(); - - expect(findFormGroup().attributes()).toMatchObject({ - label: NEXT_CLEANUP_LABEL, - }); - }); - }); - - describe('formattedValue', () => { - it.each` - valueProp | enabled | expected - ${value} | ${true} | ${value} - ${value} | ${false} | ${NOT_SCHEDULED_POLICY_TEXT} - ${undefined} | ${false} | ${NOT_SCHEDULED_POLICY_TEXT} - ${undefined} | ${true} | ${NOT_SCHEDULED_POLICY_TEXT} - `( - 'when value is $valueProp and enabled is $enabled the input value is $expected', - ({ valueProp, enabled, expected }) => { - mountComponent({ value: valueProp, enabled }); - - expect(findInput().attributes('value')).toBe(expected); - }, - ); - }); -}); diff --git a/spec/frontend/registry/settings/components/expiration_toggle_spec.js b/spec/frontend/registry/settings/components/expiration_toggle_spec.js deleted file mode 100644 index 7598f6adc89..00000000000 --- a/spec/frontend/registry/settings/components/expiration_toggle_spec.js +++ /dev/null @@ -1,77 +0,0 @@ -import { GlToggle, GlSprintf } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import { GlFormGroup } from 'jest/registry/shared/stubs'; -import component from '~/registry/settings/components/expiration_toggle.vue'; -import { - ENABLED_TOGGLE_DESCRIPTION, - DISABLED_TOGGLE_DESCRIPTION, -} 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().props('label')).toBe(component.i18n.toggleLabel); - }); - - it('has a description', () => { - mountComponent(); - - expect(findDescription().exists()).toBe(true); - }); - }); - - 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()).toMatchInterpolatedText(ENABLED_TOGGLE_DESCRIPTION); - }); - - it('says disabled when the toggle is off', () => { - mountComponent({ value: false }); - - expect(findDescription().text()).toMatchInterpolatedText(DISABLED_TOGGLE_DESCRIPTION); - }); - }); -}); diff --git a/spec/frontend/registry/settings/components/registry_settings_app_spec.js b/spec/frontend/registry/settings/components/registry_settings_app_spec.js deleted file mode 100644 index fd53efa884f..00000000000 --- a/spec/frontend/registry/settings/components/registry_settings_app_spec.js +++ /dev/null @@ -1,164 +0,0 @@ -import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import VueApollo from 'vue-apollo'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import component from '~/registry/settings/components/registry_settings_app.vue'; -import SettingsForm from '~/registry/settings/components/settings_form.vue'; -import { - FETCH_SETTINGS_ERROR_MESSAGE, - UNAVAILABLE_FEATURE_INTRO_TEXT, - UNAVAILABLE_USER_FEATURE_TEXT, -} from '~/registry/settings/constants'; -import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql'; - -import { - expirationPolicyPayload, - emptyExpirationPolicyPayload, - containerExpirationPolicyData, -} from '../mock_data'; - -const localVue = createLocalVue(); - -describe('Registry Settings App', () => { - let wrapper; - let fakeApollo; - - const defaultProvidedValues = { - projectPath: 'path', - isAdmin: false, - adminSettingsPath: 'settingsPath', - enableHistoricEntries: false, - }; - - const findSettingsComponent = () => wrapper.find(SettingsForm); - const findAlert = () => wrapper.find(GlAlert); - - const mountComponent = (provide = defaultProvidedValues, config) => { - wrapper = shallowMount(component, { - stubs: { - GlSprintf, - }, - mocks: { - $toast: { - show: jest.fn(), - }, - }, - provide, - ...config, - }); - }; - - const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => { - localVue.use(VueApollo); - - const requestHandlers = [[expirationPolicyQuery, resolver]]; - - fakeApollo = createMockApollo(requestHandlers); - mountComponent(provide, { - localVue, - apolloProvider: fakeApollo, - }); - - return requestHandlers.map((request) => request[1]); - }; - - afterEach(() => { - wrapper.destroy(); - }); - - describe('isEdited status', () => { - it.each` - description | apiResponse | workingCopy | result - ${'empty response and no changes from user'} | ${emptyExpirationPolicyPayload()} | ${{}} | ${false} - ${'empty response and changes from user'} | ${emptyExpirationPolicyPayload()} | ${{ enabled: true }} | ${true} - ${'response and no changes'} | ${expirationPolicyPayload()} | ${containerExpirationPolicyData()} | ${false} - ${'response and changes'} | ${expirationPolicyPayload()} | ${{ ...containerExpirationPolicyData(), nameRegex: '12345' }} | ${true} - ${'response and empty'} | ${expirationPolicyPayload()} | ${{}} | ${true} - `('$description', async ({ apiResponse, workingCopy, result }) => { - const requests = mountComponentWithApollo({ - provide: { ...defaultProvidedValues, enableHistoricEntries: true }, - resolver: jest.fn().mockResolvedValue(apiResponse), - }); - await Promise.all(requests); - - findSettingsComponent().vm.$emit('input', workingCopy); - - await wrapper.vm.$nextTick(); - - expect(findSettingsComponent().props('isEdited')).toBe(result); - }); - }); - - it('renders the setting form', async () => { - const requests = mountComponentWithApollo({ - resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()), - }); - await Promise.all(requests); - - expect(findSettingsComponent().exists()).toBe(true); - }); - - describe('the form is disabled', () => { - it('the form is hidden', () => { - mountComponent(); - - expect(findSettingsComponent().exists()).toBe(false); - }); - - it('shows an alert', () => { - mountComponent(); - - const text = findAlert().text(); - expect(text).toContain(UNAVAILABLE_FEATURE_INTRO_TEXT); - expect(text).toContain(UNAVAILABLE_USER_FEATURE_TEXT); - }); - - describe('an admin is visiting the page', () => { - it('shows the admin part of the alert message', () => { - mountComponent({ ...defaultProvidedValues, isAdmin: true }); - - const sprintf = findAlert().find(GlSprintf); - expect(sprintf.text()).toBe('administration settings'); - expect(sprintf.find(GlLink).attributes('href')).toBe( - defaultProvidedValues.adminSettingsPath, - ); - }); - }); - }); - - describe('fetchSettingsError', () => { - beforeEach(() => { - const requests = mountComponentWithApollo({ - resolver: jest.fn().mockRejectedValue(new Error('GraphQL error')), - }); - return Promise.all(requests); - }); - - it('the form is hidden', () => { - expect(findSettingsComponent().exists()).toBe(false); - }); - - it('shows an alert', () => { - expect(findAlert().html()).toContain(FETCH_SETTINGS_ERROR_MESSAGE); - }); - }); - - describe('empty API response', () => { - it.each` - enableHistoricEntries | isShown - ${true} | ${true} - ${false} | ${false} - `('is $isShown that the form is shown', async ({ enableHistoricEntries, isShown }) => { - const requests = mountComponentWithApollo({ - provide: { - ...defaultProvidedValues, - enableHistoricEntries, - }, - resolver: jest.fn().mockResolvedValue(emptyExpirationPolicyPayload()), - }); - await Promise.all(requests); - - expect(findSettingsComponent().exists()).toBe(isShown); - }); - }); -}); diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js deleted file mode 100644 index ad94da6ca66..00000000000 --- a/spec/frontend/registry/settings/components/settings_form_spec.js +++ /dev/null @@ -1,460 +0,0 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import VueApollo from 'vue-apollo'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import waitForPromises from 'helpers/wait_for_promises'; -import component from '~/registry/settings/components/settings_form.vue'; -import { - UPDATE_SETTINGS_ERROR_MESSAGE, - UPDATE_SETTINGS_SUCCESS_MESSAGE, -} from '~/registry/settings/constants'; -import updateContainerExpirationPolicyMutation from '~/registry/settings/graphql/mutations/update_container_expiration_policy.mutation.graphql'; -import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql'; -import Tracking from '~/tracking'; -import { GlCard, GlLoadingIcon } from '../../shared/stubs'; -import { expirationPolicyPayload, expirationPolicyMutationPayload } from '../mock_data'; - -const localVue = createLocalVue(); - -describe('Settings Form', () => { - let wrapper; - let fakeApollo; - - const defaultProvidedValues = { - projectPath: 'path', - }; - - const { - data: { - project: { containerExpirationPolicy }, - }, - } = expirationPolicyPayload(); - - const defaultProps = { - value: { ...containerExpirationPolicy }, - }; - - const trackingPayload = { - label: 'docker_container_retention_and_expiration_policies', - }; - - const findForm = () => wrapper.find({ ref: 'form-element' }); - - const findCancelButton = () => wrapper.find('[data-testid="cancel-button"'); - const findSaveButton = () => wrapper.find('[data-testid="save-button"'); - const findEnableToggle = () => wrapper.find('[data-testid="enable-toggle"]'); - const findCadenceDropdown = () => wrapper.find('[data-testid="cadence-dropdown"]'); - const findKeepNDropdown = () => wrapper.find('[data-testid="keep-n-dropdown"]'); - const findKeepRegexInput = () => wrapper.find('[data-testid="keep-regex-input"]'); - const findOlderThanDropdown = () => wrapper.find('[data-testid="older-than-dropdown"]'); - const findRemoveRegexInput = () => wrapper.find('[data-testid="remove-regex-input"]'); - - const mountComponent = ({ - props = defaultProps, - data, - config, - provide = defaultProvidedValues, - mocks, - } = {}) => { - wrapper = shallowMount(component, { - stubs: { - GlCard, - GlLoadingIcon, - }, - propsData: { ...props }, - provide, - data() { - return { - ...data, - }; - }, - mocks: { - $toast: { - show: jest.fn(), - }, - ...mocks, - }, - ...config, - }); - }; - - const mountComponentWithApollo = ({ - provide = defaultProvidedValues, - mutationResolver, - queryPayload = expirationPolicyPayload(), - } = {}) => { - localVue.use(VueApollo); - - const requestHandlers = [ - [updateContainerExpirationPolicyMutation, mutationResolver], - [expirationPolicyQuery, jest.fn().mockResolvedValue(queryPayload)], - ]; - - fakeApollo = createMockApollo(requestHandlers); - - // This component does not do the query directly, but we need a proper cache to update - fakeApollo.defaultClient.cache.writeQuery({ - query: expirationPolicyQuery, - variables: { - projectPath: provide.projectPath, - }, - ...queryPayload, - }); - - // we keep in sync what prop we pass to the component with the cache - const { - data: { - project: { containerExpirationPolicy: value }, - }, - } = queryPayload; - - mountComponent({ - provide, - props: { - ...defaultProps, - value, - }, - config: { - localVue, - apolloProvider: fakeApollo, - }, - }); - }; - - beforeEach(() => { - jest.spyOn(Tracking, 'event'); - }); - - afterEach(() => { - wrapper.destroy(); - }); - - describe.each` - model | finder | fieldName | type | defaultValue - ${'enabled'} | ${findEnableToggle} | ${'Enable'} | ${'toggle'} | ${false} - ${'cadence'} | ${findCadenceDropdown} | ${'Cadence'} | ${'dropdown'} | ${'EVERY_DAY'} - ${'keepN'} | ${findKeepNDropdown} | ${'Keep N'} | ${'dropdown'} | ${'TEN_TAGS'} - ${'nameRegexKeep'} | ${findKeepRegexInput} | ${'Keep Regex'} | ${'textarea'} | ${''} - ${'olderThan'} | ${findOlderThanDropdown} | ${'OlderThan'} | ${'dropdown'} | ${'NINETY_DAYS'} - ${'nameRegex'} | ${findRemoveRegexInput} | ${'Remove regex'} | ${'textarea'} | ${''} - `('$fieldName', ({ model, finder, type, defaultValue }) => { - it('matches snapshot', () => { - mountComponent(); - - expect(finder().element).toMatchSnapshot(); - }); - - it('input event triggers a model update', () => { - mountComponent(); - - finder().vm.$emit('input', 'foo'); - expect(wrapper.emitted('input')[0][0]).toMatchObject({ - [model]: 'foo', - }); - }); - - it('shows the default option when none are selected', () => { - mountComponent({ props: { value: {} } }); - expect(finder().props('value')).toEqual(defaultValue); - }); - - if (type !== 'toggle') { - it.each` - isLoading | mutationLoading | enabledValue - ${false} | ${false} | ${false} - ${true} | ${false} | ${false} - ${true} | ${true} | ${true} - ${false} | ${true} | ${true} - ${false} | ${false} | ${false} - `( - 'is disabled when is loading is $isLoading, mutationLoading is $mutationLoading and enabled is $enabledValue', - ({ isLoading, mutationLoading, enabledValue }) => { - mountComponent({ - props: { isLoading, value: { enabled: enabledValue } }, - data: { mutationLoading }, - }); - expect(finder().props('disabled')).toEqual(true); - }, - ); - } else { - it.each` - isLoading | mutationLoading - ${true} | ${false} - ${true} | ${true} - ${false} | ${true} - `( - 'is disabled when is loading is $isLoading and mutationLoading is $mutationLoading', - ({ isLoading, mutationLoading }) => { - mountComponent({ - props: { isLoading, value: {} }, - data: { mutationLoading }, - }); - expect(finder().props('disabled')).toEqual(true); - }, - ); - } - - if (type === 'textarea') { - it('input event updates the api error property', async () => { - const apiErrors = { [model]: 'bar' }; - mountComponent({ data: { apiErrors } }); - - finder().vm.$emit('input', 'foo'); - expect(finder().props('error')).toEqual('bar'); - - await wrapper.vm.$nextTick(); - - expect(finder().props('error')).toEqual(''); - }); - - it('validation event updates buttons disabled state', async () => { - mountComponent(); - - expect(findSaveButton().props('disabled')).toBe(false); - - finder().vm.$emit('validation', false); - - await wrapper.vm.$nextTick(); - - expect(findSaveButton().props('disabled')).toBe(true); - }); - } - - if (type === 'dropdown') { - it('has the correct formOptions', () => { - mountComponent(); - expect(finder().props('formOptions')).toEqual(wrapper.vm.$options.formOptions[model]); - }); - } - }); - - describe('form', () => { - describe('form reset event', () => { - it('calls the appropriate function', () => { - mountComponent(); - - findForm().trigger('reset'); - - expect(wrapper.emitted('reset')).toEqual([[]]); - }); - - it('tracks the reset event', () => { - mountComponent(); - - findForm().trigger('reset'); - - expect(Tracking.event).toHaveBeenCalledWith(undefined, 'reset_form', trackingPayload); - }); - - it('resets the errors objects', async () => { - mountComponent({ - data: { apiErrors: { nameRegex: 'bar' }, localErrors: { nameRegexKeep: false } }, - }); - - findForm().trigger('reset'); - - await wrapper.vm.$nextTick(); - - expect(findKeepRegexInput().props('error')).toBe(''); - expect(findRemoveRegexInput().props('error')).toBe(''); - expect(findSaveButton().props('disabled')).toBe(false); - }); - }); - - describe('form submit event ', () => { - it('save has type submit', () => { - mountComponent(); - - expect(findSaveButton().attributes('type')).toBe('submit'); - }); - - it('dispatches the correct apollo mutation', () => { - const mutationResolver = jest.fn().mockResolvedValue(expirationPolicyMutationPayload()); - mountComponentWithApollo({ - mutationResolver, - }); - - findForm().trigger('submit'); - - expect(mutationResolver).toHaveBeenCalled(); - }); - - it('saves the default values when a value is missing did not change the default options', async () => { - const mutationResolver = jest.fn().mockResolvedValue(expirationPolicyMutationPayload()); - mountComponentWithApollo({ - mutationResolver, - queryPayload: expirationPolicyPayload({ keepN: null, cadence: null, olderThan: null }), - }); - - await waitForPromises(); - - findForm().trigger('submit'); - - expect(mutationResolver).toHaveBeenCalledWith({ - input: { - cadence: 'EVERY_DAY', - enabled: true, - keepN: 'TEN_TAGS', - nameRegex: 'asdasdssssdfdf', - nameRegexKeep: 'sss', - olderThan: 'NINETY_DAYS', - projectPath: 'path', - }, - }); - }); - - it('tracks the submit event', () => { - mountComponentWithApollo({ - mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()), - }); - - findForm().trigger('submit'); - - expect(Tracking.event).toHaveBeenCalledWith(undefined, 'submit_form', trackingPayload); - }); - - it('show a success toast when submit succeed', async () => { - mountComponentWithApollo({ - mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()), - }); - - findForm().trigger('submit'); - await waitForPromises(); - await wrapper.vm.$nextTick(); - - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE, { - type: 'success', - }); - }); - - describe('when submit fails', () => { - describe('user recoverable errors', () => { - it('when there is an error is shown in a toast', async () => { - mountComponentWithApollo({ - mutationResolver: jest - .fn() - .mockResolvedValue(expirationPolicyMutationPayload({ errors: ['foo'] })), - }); - - findForm().trigger('submit'); - await waitForPromises(); - await wrapper.vm.$nextTick(); - - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo', { - type: 'error', - }); - }); - }); - - describe('global errors', () => { - it('shows an error', async () => { - mountComponentWithApollo({ - mutationResolver: jest.fn().mockRejectedValue(expirationPolicyMutationPayload()), - }); - - findForm().trigger('submit'); - await waitForPromises(); - await wrapper.vm.$nextTick(); - - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE, { - type: 'error', - }); - }); - - it('parses the error messages', async () => { - const mutate = jest.fn().mockRejectedValue({ - graphQLErrors: [ - { - extensions: { - problems: [{ path: ['nameRegexKeep'], message: 'baz' }], - }, - }, - ], - }); - mountComponent({ mocks: { $apollo: { mutate } } }); - - findForm().trigger('submit'); - await waitForPromises(); - await wrapper.vm.$nextTick(); - - expect(findKeepRegexInput().props('error')).toEqual('baz'); - }); - }); - }); - }); - }); - - describe('form actions', () => { - describe('cancel button', () => { - it('has type reset', () => { - mountComponent(); - - expect(findCancelButton().attributes('type')).toBe('reset'); - }); - - it.each` - isLoading | isEdited | mutationLoading - ${true} | ${true} | ${true} - ${false} | ${true} | ${true} - ${false} | ${false} | ${true} - ${true} | ${false} | ${false} - ${false} | ${false} | ${false} - `( - 'when isLoading is $isLoading, isEdited is $isEdited and mutationLoading is $mutationLoading is disabled', - ({ isEdited, isLoading, mutationLoading }) => { - mountComponent({ - props: { ...defaultProps, isEdited, isLoading }, - data: { mutationLoading }, - }); - - expect(findCancelButton().props('disabled')).toBe(true); - }, - ); - }); - - describe('submit button', () => { - it('has type submit', () => { - mountComponent(); - - expect(findSaveButton().attributes('type')).toBe('submit'); - }); - - it.each` - isLoading | localErrors | mutationLoading - ${true} | ${{}} | ${true} - ${true} | ${{}} | ${false} - ${false} | ${{}} | ${true} - ${false} | ${{ foo: false }} | ${true} - ${true} | ${{ foo: false }} | ${false} - ${false} | ${{ foo: false }} | ${false} - `( - 'when isLoading is $isLoading, localErrors is $localErrors and mutationLoading is $mutationLoading is disabled', - ({ localErrors, isLoading, mutationLoading }) => { - mountComponent({ - props: { ...defaultProps, isLoading }, - data: { mutationLoading, localErrors }, - }); - - expect(findSaveButton().props('disabled')).toBe(true); - }, - ); - - it.each` - isLoading | mutationLoading | showLoading - ${true} | ${true} | ${true} - ${true} | ${false} | ${true} - ${false} | ${true} | ${true} - ${false} | ${false} | ${false} - `( - 'when isLoading is $isLoading and mutationLoading is $mutationLoading is $showLoading that the loading icon is shown', - ({ isLoading, mutationLoading, showLoading }) => { - mountComponent({ - props: { ...defaultProps, isLoading }, - data: { mutationLoading }, - }); - - expect(findSaveButton().props('loading')).toBe(showLoading); - }, - ); - }); - }); -}); diff --git a/spec/frontend/registry/settings/graphql/cache_updated_spec.js b/spec/frontend/registry/settings/graphql/cache_updated_spec.js deleted file mode 100644 index 73655b6917b..00000000000 --- a/spec/frontend/registry/settings/graphql/cache_updated_spec.js +++ /dev/null @@ -1,56 +0,0 @@ -import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql'; -import { updateContainerExpirationPolicy } from '~/registry/settings/graphql/utils/cache_update'; - -describe('Registry settings cache update', () => { - let client; - - const payload = { - data: { - updateContainerExpirationPolicy: { - containerExpirationPolicy: { - enabled: true, - }, - }, - }, - }; - - const cacheMock = { - project: { - containerExpirationPolicy: { - enabled: false, - }, - }, - }; - - const queryAndVariables = { - query: expirationPolicyQuery, - variables: { projectPath: 'foo' }, - }; - - beforeEach(() => { - client = { - readQuery: jest.fn().mockReturnValue(cacheMock), - writeQuery: jest.fn(), - }; - }); - describe('Registry settings cache update', () => { - it('calls readQuery', () => { - updateContainerExpirationPolicy('foo')(client, payload); - expect(client.readQuery).toHaveBeenCalledWith(queryAndVariables); - }); - - it('writes the correct result in the cache', () => { - updateContainerExpirationPolicy('foo')(client, payload); - expect(client.writeQuery).toHaveBeenCalledWith({ - ...queryAndVariables, - data: { - project: { - containerExpirationPolicy: { - enabled: true, - }, - }, - }, - }); - }); - }); -}); diff --git a/spec/frontend/registry/settings/mock_data.js b/spec/frontend/registry/settings/mock_data.js deleted file mode 100644 index 9778f409010..00000000000 --- a/spec/frontend/registry/settings/mock_data.js +++ /dev/null @@ -1,40 +0,0 @@ -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: { - ...containerExpirationPolicyData(), - ...override, - }, - }, - }, -}); - -export const emptyExpirationPolicyPayload = () => ({ - data: { - project: { - containerExpirationPolicy: {}, - }, - }, -}); - -export const expirationPolicyMutationPayload = ({ override, errors = [] } = {}) => ({ - data: { - updateContainerExpirationPolicy: { - containerExpirationPolicy: { - ...containerExpirationPolicyData(), - ...override, - }, - errors, - }, - }, -}); diff --git a/spec/frontend/registry/settings/utils_spec.js b/spec/frontend/registry/settings/utils_spec.js deleted file mode 100644 index 7bc627908af..00000000000 --- a/spec/frontend/registry/settings/utils_spec.js +++ /dev/null @@ -1,37 +0,0 @@ -import { - formOptionsGenerator, - optionLabelGenerator, - olderThanTranslationGenerator, -} from '~/registry/settings/utils'; - -describe('Utils', () => { - describe('optionLabelGenerator', () => { - it('returns an array with a set label', () => { - const result = optionLabelGenerator( - [{ variable: 1 }, { variable: 2 }], - olderThanTranslationGenerator, - ); - expect(result).toEqual([ - { variable: 1, label: '1 day' }, - { variable: 2, label: '2 days' }, - ]); - }); - }); - - describe('formOptionsGenerator', () => { - it('returns an object containing olderThan', () => { - expect(formOptionsGenerator().olderThan).toBeDefined(); - expect(formOptionsGenerator().olderThan).toMatchSnapshot(); - }); - - it('returns an object containing cadence', () => { - expect(formOptionsGenerator().cadence).toBeDefined(); - expect(formOptionsGenerator().cadence).toMatchSnapshot(); - }); - - it('returns an object containing keepN', () => { - expect(formOptionsGenerator().keepN).toBeDefined(); - expect(formOptionsGenerator().keepN).toMatchSnapshot(); - }); - }); -}); |