diff options
Diffstat (limited to 'spec/frontend/packages_and_registries/settings/project')
9 files changed, 316 insertions, 135 deletions
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js new file mode 100644 index 00000000000..8b60f31512b --- /dev/null +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js @@ -0,0 +1,164 @@ +import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import component from '~/packages_and_registries/settings/project/components/cleanup_image_tags.vue'; +import ContainerExpirationPolicyForm from '~/packages_and_registries/settings/project/components/container_expiration_policy_form.vue'; +import { + CONTAINER_CLEANUP_POLICY_TITLE, + CONTAINER_CLEANUP_POLICY_DESCRIPTION, + FETCH_SETTINGS_ERROR_MESSAGE, + UNAVAILABLE_FEATURE_INTRO_TEXT, + UNAVAILABLE_USER_FEATURE_TEXT, +} from '~/packages_and_registries/settings/project/constants'; +import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql'; + +import { + expirationPolicyPayload, + emptyExpirationPolicyPayload, + containerExpirationPolicyData, +} from '../mock_data'; + +describe('Cleanup image tags project settings', () => { + let wrapper; + let fakeApollo; + + const defaultProvidedValues = { + projectPath: 'path', + isAdmin: false, + adminSettingsPath: 'settingsPath', + enableHistoricEntries: false, + helpPagePath: 'helpPagePath', + showCleanupPolicyLink: false, + }; + + const findFormComponent = () => wrapper.findComponent(ContainerExpirationPolicyForm); + const findAlert = () => wrapper.findComponent(GlAlert); + const findTitle = () => wrapper.findByTestId('title'); + const findDescription = () => wrapper.findByTestId('description'); + + const mountComponent = (provide = defaultProvidedValues, config) => { + wrapper = shallowMountExtended(component, { + stubs: { + GlSprintf, + }, + provide, + ...config, + }); + }; + + const mountComponentWithApollo = ({ provide = defaultProvidedValues, resolver } = {}) => { + Vue.use(VueApollo); + + const requestHandlers = [[expirationPolicyQuery, resolver]]; + + fakeApollo = createMockApollo(requestHandlers); + mountComponent(provide, { + apolloProvider: fakeApollo, + }); + }; + + 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 }) => { + mountComponentWithApollo({ + provide: { ...defaultProvidedValues, enableHistoricEntries: true }, + resolver: jest.fn().mockResolvedValue(apiResponse), + }); + await waitForPromises(); + + findFormComponent().vm.$emit('input', workingCopy); + + await waitForPromises(); + + expect(findFormComponent().props('isEdited')).toBe(result); + }); + }); + + it('renders the setting form', async () => { + mountComponentWithApollo({ + resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()), + }); + await waitForPromises(); + + expect(findFormComponent().exists()).toBe(true); + expect(findTitle().text()).toMatchInterpolatedText(CONTAINER_CLEANUP_POLICY_TITLE); + expect(findDescription().text()).toMatchInterpolatedText(CONTAINER_CLEANUP_POLICY_DESCRIPTION); + }); + + describe('the form is disabled', () => { + it('hides the form', () => { + mountComponent(); + + expect(findFormComponent().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().findComponent(GlSprintf); + expect(sprintf.text()).toBe('administration settings'); + expect(sprintf.findComponent(GlLink).attributes('href')).toBe( + defaultProvidedValues.adminSettingsPath, + ); + }); + }); + }); + + describe('fetchSettingsError', () => { + beforeEach(async () => { + mountComponentWithApollo({ + resolver: jest.fn().mockRejectedValue(new Error('GraphQL error')), + }); + await waitForPromises(); + }); + + it('hides the form', () => { + expect(findFormComponent().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 }) => { + mountComponentWithApollo({ + provide: { + ...defaultProvidedValues, + enableHistoricEntries, + }, + resolver: jest.fn().mockResolvedValue(emptyExpirationPolicyPayload()), + }); + await waitForPromises(); + + expect(findFormComponent().exists()).toBe(isShown); + }); + }); +}); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js index ca44e77e694..8e08864bdb8 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_form_spec.js @@ -2,13 +2,11 @@ import { shallowMount } from '@vue/test-utils'; import VueApollo from 'vue-apollo'; import Vue, { nextTick } from 'vue'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { GlCard, GlLoadingIcon } from 'jest/packages_and_registries/shared/stubs'; import component from '~/packages_and_registries/settings/project/components/container_expiration_policy_form.vue'; -import { - UPDATE_SETTINGS_ERROR_MESSAGE, - UPDATE_SETTINGS_SUCCESS_MESSAGE, -} from '~/packages_and_registries/settings/project/constants'; +import { UPDATE_SETTINGS_ERROR_MESSAGE } from '~/packages_and_registries/settings/project/constants'; import updateContainerExpirationPolicyMutation from '~/packages_and_registries/settings/project/graphql/mutations/update_container_expiration_policy.mutation.graphql'; import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql'; import Tracking from '~/tracking'; @@ -20,6 +18,7 @@ describe('Container Expiration Policy Settings Form', () => { const defaultProvidedValues = { projectPath: 'path', + projectSettingsPath: 'settings-path', }; const { @@ -36,7 +35,7 @@ describe('Container Expiration Policy Settings Form', () => { label: 'docker_container_retention_and_expiration_policies', }; - const findForm = () => wrapper.find({ ref: 'form-element' }); + const findForm = () => wrapper.find('form'); const findCancelButton = () => wrapper.find('[data-testid="cancel-button"'); const findSaveButton = () => wrapper.find('[data-testid="save-button"'); @@ -208,7 +207,9 @@ describe('Container Expiration Policy Settings Form', () => { }); it('validation event updates buttons disabled state', async () => { - mountComponent(); + mountComponent({ + props: { ...defaultProps, isEdited: true }, + }); expect(findSaveButton().props('disabled')).toBe(false); @@ -229,52 +230,22 @@ describe('Container Expiration Policy Settings Form', () => { }); 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 nextTick(); + describe('form submit event', () => { + useMockLocationHelper(); - 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', () => { + it('dispatches the correct apollo mutation', async () => { const mutationResolver = jest.fn().mockResolvedValue(expirationPolicyMutationPayload()); mountComponentWithApollo({ mutationResolver, }); - findForm().trigger('submit'); + await submitForm(); expect(mutationResolver).toHaveBeenCalled(); }); @@ -286,9 +257,7 @@ describe('Container Expiration Policy Settings Form', () => { queryPayload: expirationPolicyPayload({ keepN: null, cadence: null, olderThan: null }), }); - await waitForPromises(); - - findForm().trigger('submit'); + await submitForm(); expect(mutationResolver).toHaveBeenCalledWith({ input: { @@ -303,24 +272,26 @@ describe('Container Expiration Policy Settings Form', () => { }); }); - it('tracks the submit event', () => { + it('tracks the submit event', async () => { mountComponentWithApollo({ mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()), }); - findForm().trigger('submit'); + await submitForm(); expect(Tracking.event).toHaveBeenCalledWith(undefined, 'submit_form', trackingPayload); }); - it('show a success toast when submit succeed', async () => { + it('redirects to package and registry project settings page when submitted successfully', async () => { mountComponentWithApollo({ mutationResolver: jest.fn().mockResolvedValue(expirationPolicyMutationPayload()), }); await submitForm(); - expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE); + expect(window.location.href.endsWith('settings-path?showSetupSuccessAlert=true')).toBe( + true, + ); }); describe('when submit fails', () => { @@ -348,6 +319,7 @@ describe('Container Expiration Policy Settings Form', () => { await submitForm(); expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE); + expect(window.location.href).toBeUndefined(); }); it('parses the error messages', async () => { @@ -375,24 +347,24 @@ describe('Container Expiration Policy Settings Form', () => { describe('form actions', () => { describe('cancel button', () => { - it('has type reset', () => { + it('links to project package and registry settings path', () => { mountComponent(); - expect(findCancelButton().attributes('type')).toBe('reset'); + expect(findCancelButton().attributes('href')).toBe( + defaultProvidedValues.projectSettingsPath, + ); }); it.each` - isLoading | isEdited | mutationLoading - ${true} | ${true} | ${true} - ${false} | ${true} | ${true} - ${false} | ${false} | ${true} - ${true} | ${false} | ${false} - ${false} | ${false} | ${false} + isLoading | mutationLoading + ${true} | ${true} + ${false} | ${true} + ${true} | ${false} `( - 'when isLoading is $isLoading, isEdited is $isEdited and mutationLoading is $mutationLoading is disabled', - ({ isEdited, isLoading, mutationLoading }) => { + 'is disabled when isLoading is $isLoading and mutationLoading is $mutationLoading', + ({ isLoading, mutationLoading }) => { mountComponent({ - props: { ...defaultProps, isEdited, isLoading }, + props: { ...defaultProps, isLoading }, data: { mutationLoading }, }); @@ -409,18 +381,19 @@ describe('Container Expiration Policy Settings Form', () => { }); it.each` - isLoading | localErrors | mutationLoading - ${true} | ${{}} | ${true} - ${true} | ${{}} | ${false} - ${false} | ${{}} | ${true} - ${false} | ${{ foo: false }} | ${true} - ${true} | ${{ foo: false }} | ${false} - ${false} | ${{ foo: false }} | ${false} + isLoading | isEdited | localErrors | mutationLoading + ${true} | ${false} | ${{}} | ${true} + ${true} | ${false} | ${{}} | ${false} + ${false} | ${false} | ${{}} | ${true} + ${false} | ${false} | ${{}} | ${false} + ${false} | ${false} | ${{ foo: false }} | ${true} + ${true} | ${false} | ${{ foo: false }} | ${false} + ${false} | ${false} | ${{ foo: false }} | ${false} `( - 'when isLoading is $isLoading, localErrors is $localErrors and mutationLoading is $mutationLoading is disabled', - ({ localErrors, isLoading, mutationLoading }) => { + 'is disabled when isLoading is $isLoading, isEdited is $isEdited, localErrors is $localErrors and mutationLoading is $mutationLoading', + ({ localErrors, isEdited, isLoading, mutationLoading }) => { mountComponent({ - props: { ...defaultProps, isLoading }, + props: { ...defaultProps, isEdited, isLoading }, data: { mutationLoading, localErrors }, }); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js index d83c717da6a..35baeaeac61 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js @@ -1,12 +1,14 @@ -import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; +import { GlAlert, GlSprintf, GlLink, GlCard } from '@gitlab/ui'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import component from '~/packages_and_registries/settings/project/components/container_expiration_policy.vue'; -import ContainerExpirationPolicyForm from '~/packages_and_registries/settings/project/components/container_expiration_policy_form.vue'; import { + CONTAINER_CLEANUP_POLICY_EDIT_RULES, + CONTAINER_CLEANUP_POLICY_SET_RULES, + CONTAINER_CLEANUP_POLICY_RULES_DESCRIPTION, FETCH_SETTINGS_ERROR_MESSAGE, UNAVAILABLE_FEATURE_INTRO_TEXT, UNAVAILABLE_USER_FEATURE_TEXT, @@ -14,11 +16,7 @@ import { import expirationPolicyQuery from '~/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql'; import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue'; -import { - expirationPolicyPayload, - emptyExpirationPolicyPayload, - containerExpirationPolicyData, -} from '../mock_data'; +import { expirationPolicyPayload, emptyExpirationPolicyPayload } from '../mock_data'; describe('Container expiration policy project settings', () => { let wrapper; @@ -28,17 +26,19 @@ describe('Container expiration policy project settings', () => { projectPath: 'path', isAdmin: false, adminSettingsPath: 'settingsPath', + cleanupSettingsPath: 'cleanupSettingsPath', enableHistoricEntries: false, helpPagePath: 'helpPagePath', - showCleanupPolicyLink: false, }; - const findFormComponent = () => wrapper.find(ContainerExpirationPolicyForm); - const findAlert = () => wrapper.find(GlAlert); - const findSettingsBlock = () => wrapper.find(SettingsBlock); + const findFormComponent = () => wrapper.findComponent(GlCard); + const findDescription = () => wrapper.findByTestId('description'); + const findButton = () => wrapper.findByTestId('rules-button'); + const findAlert = () => wrapper.findComponent(GlAlert); + const findSettingsBlock = () => wrapper.findComponent(SettingsBlock); const mountComponent = (provide = defaultProvidedValues, config) => { - wrapper = shallowMount(component, { + wrapper = shallowMountExtended(component, { stubs: { GlSprintf, SettingsBlock, @@ -63,37 +63,19 @@ describe('Container expiration policy project settings', () => { 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 }) => { - mountComponentWithApollo({ - provide: { ...defaultProvidedValues, enableHistoricEntries: true }, - resolver: jest.fn().mockResolvedValue(apiResponse), - }); - await waitForPromises(); - - findFormComponent().vm.$emit('input', workingCopy); - - await waitForPromises(); - - expect(findFormComponent().props('isEdited')).toBe(result); - }); - }); - it('renders the setting form', async () => { mountComponentWithApollo({ resolver: jest.fn().mockResolvedValue(expirationPolicyPayload()), }); await waitForPromises(); - expect(findFormComponent().exists()).toBe(true); expect(findSettingsBlock().exists()).toBe(true); + expect(findFormComponent().exists()).toBe(true); + expect(findDescription().text()).toMatchInterpolatedText( + CONTAINER_CLEANUP_POLICY_RULES_DESCRIPTION, + ); + expect(findButton().text()).toMatchInterpolatedText(CONTAINER_CLEANUP_POLICY_EDIT_RULES); + expect(findButton().attributes('href')).toBe(defaultProvidedValues.cleanupSettingsPath); }); describe('the form is disabled', () => { @@ -115,9 +97,9 @@ describe('Container expiration policy project settings', () => { it('shows the admin part of the alert message', () => { mountComponent({ ...defaultProvidedValues, isAdmin: true }); - const sprintf = findAlert().find(GlSprintf); + const sprintf = findAlert().findComponent(GlSprintf); expect(sprintf.text()).toBe('administration settings'); - expect(sprintf.find(GlLink).attributes('href')).toBe( + expect(sprintf.findComponent(GlLink).attributes('href')).toBe( defaultProvidedValues.adminSettingsPath, ); }); @@ -157,6 +139,10 @@ describe('Container expiration policy project settings', () => { await waitForPromises(); expect(findFormComponent().exists()).toBe(isShown); + if (isShown) { + expect(findButton().text()).toMatchInterpolatedText(CONTAINER_CLEANUP_POLICY_SET_RULES); + expect(findButton().attributes('href')).toBe(defaultProvidedValues.cleanupSettingsPath); + } }); }); }); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js index 8b99ac6b06c..ae41fdf65e0 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js @@ -14,8 +14,8 @@ describe('ExpirationDropdown', () => { ], }; - const findFormSelect = () => wrapper.find(GlFormSelect); - const findFormGroup = () => wrapper.find(GlFormGroup); + const findFormSelect = () => wrapper.findComponent(GlFormSelect); + const findFormGroup = () => wrapper.findComponent(GlFormGroup); const findDescription = () => wrapper.find('[data-testid="description"]'); const findOptions = () => wrapper.findAll('[data-testid="option"]'); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js index 6b681924fcf..1cea0704154 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js @@ -16,11 +16,11 @@ describe('ExpirationInput', () => { const tagsRegexHelpPagePath = 'fooPath'; - const findInput = () => wrapper.find(GlFormInput); - const findFormGroup = () => wrapper.find(GlFormGroup); + const findInput = () => wrapper.findComponent(GlFormInput); + const findFormGroup = () => wrapper.findComponent(GlFormGroup); const findLabel = () => wrapper.find('[data-testid="label"]'); const findDescription = () => wrapper.find('[data-testid="description"]'); - const findDescriptionLink = () => wrapper.find(GlLink); + const findDescriptionLink = () => wrapper.findComponent(GlLink); const mountComponent = (props) => { wrapper = shallowMount(component, { diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js index 94f7783afe7..653f2a8b40e 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js @@ -11,8 +11,8 @@ describe('ExpirationToggle', () => { let wrapper; const value = 'foo'; - const findInput = () => wrapper.find(GlFormInput); - const findFormGroup = () => wrapper.find(GlFormGroup); + const findInput = () => wrapper.findComponent(GlFormInput); + const findFormGroup = () => wrapper.findComponent(GlFormGroup); const mountComponent = (propsData) => { wrapper = shallowMount(component, { diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js index 45039614e49..55a66cebd83 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js @@ -10,7 +10,7 @@ import { describe('ExpirationToggle', () => { let wrapper; - const findToggle = () => wrapper.find(GlToggle); + const findToggle = () => wrapper.findComponent(GlToggle); const findDescription = () => wrapper.find('[data-testid="description"]'); const mountComponent = (propsData) => { diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js index 86f45d78bae..daf0ee85fdf 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/packages_cleanup_policy_form_spec.js @@ -39,7 +39,7 @@ describe('Packages Cleanup Policy Settings Form', () => { label: 'packages_cleanup_policies', }; - const findForm = () => wrapper.find({ ref: 'form-element' }); + const findForm = () => wrapper.findComponent({ ref: 'form-element' }); const findSaveButton = () => wrapper.findByTestId('save-button'); const findKeepNDuplicatedPackageFilesDropdown = () => wrapper.findByTestId('keep-n-duplicated-package-files-dropdown'); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js index f576bc79eae..07d13839c61 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/registry_settings_app_spec.js @@ -1,41 +1,99 @@ +import { GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; +import waitForPromises from 'helpers/wait_for_promises'; +import setWindowLocation from 'helpers/set_window_location_helper'; +import * as commonUtils from '~/lib/utils/common_utils'; import component from '~/packages_and_registries/settings/project/components/registry_settings_app.vue'; import ContainerExpirationPolicy from '~/packages_and_registries/settings/project/components/container_expiration_policy.vue'; import PackagesCleanupPolicy from '~/packages_and_registries/settings/project/components/packages_cleanup_policy.vue'; +import { + SHOW_SETUP_SUCCESS_ALERT, + UPDATE_SETTINGS_SUCCESS_MESSAGE, +} from '~/packages_and_registries/settings/project/constants'; + +jest.mock('~/lib/utils/common_utils'); describe('Registry Settings app', () => { let wrapper; - const findContainerExpirationPolicy = () => wrapper.find(ContainerExpirationPolicy); - const findPackagesCleanupPolicy = () => wrapper.find(PackagesCleanupPolicy); + const findContainerExpirationPolicy = () => wrapper.findComponent(ContainerExpirationPolicy); + const findPackagesCleanupPolicy = () => wrapper.findComponent(PackagesCleanupPolicy); + const findAlert = () => wrapper.findComponent(GlAlert); afterEach(() => { wrapper.destroy(); wrapper = null; }); - const mountComponent = (provide) => { + const defaultProvide = { + showContainerRegistrySettings: true, + showPackageRegistrySettings: true, + }; + + const mountComponent = (provide = defaultProvide) => { wrapper = shallowMount(component, { provide, }); }; - it.each` - showContainerRegistrySettings | showPackageRegistrySettings - ${true} | ${false} - ${true} | ${true} - ${false} | ${true} - ${false} | ${false} - `( - 'container expiration policy $showContainerRegistrySettings and package cleanup policy is $showPackageRegistrySettings', - ({ showContainerRegistrySettings, showPackageRegistrySettings }) => { - mountComponent({ - showContainerRegistrySettings, - showPackageRegistrySettings, + describe('container policy success alert handling', () => { + const originalLocation = window.location.href; + const search = `?${SHOW_SETUP_SUCCESS_ALERT}=true`; + + beforeEach(() => { + setWindowLocation(search); + }); + + afterEach(() => { + setWindowLocation(originalLocation); + }); + + it(`renders alert if the query string contains ${SHOW_SETUP_SUCCESS_ALERT}`, async () => { + mountComponent(); + + await waitForPromises(); + + expect(findAlert().exists()).toBe(true); + expect(findAlert().props()).toMatchObject({ + dismissible: true, + variant: 'success', }); + expect(findAlert().text()).toMatchInterpolatedText(UPDATE_SETTINGS_SUCCESS_MESSAGE); + }); + + it('calls historyReplaceState with a clean url', () => { + mountComponent(); + + expect(commonUtils.historyReplaceState).toHaveBeenCalledWith(originalLocation); + }); + + it(`does nothing if the query string does not contain ${SHOW_SETUP_SUCCESS_ALERT}`, () => { + setWindowLocation('?'); + mountComponent(); - expect(findContainerExpirationPolicy().exists()).toBe(showContainerRegistrySettings); - expect(findPackagesCleanupPolicy().exists()).toBe(showPackageRegistrySettings); - }, - ); + expect(findAlert().exists()).toBe(false); + expect(commonUtils.historyReplaceState).not.toHaveBeenCalled(); + }); + }); + + describe('settings', () => { + it.each` + showContainerRegistrySettings | showPackageRegistrySettings + ${true} | ${false} + ${true} | ${true} + ${false} | ${true} + ${false} | ${false} + `( + 'container expiration policy $showContainerRegistrySettings and package cleanup policy is $showPackageRegistrySettings', + ({ showContainerRegistrySettings, showPackageRegistrySettings }) => { + mountComponent({ + showContainerRegistrySettings, + showPackageRegistrySettings, + }); + + expect(findContainerExpirationPolicy().exists()).toBe(showContainerRegistrySettings); + expect(findPackagesCleanupPolicy().exists()).toBe(showPackageRegistrySettings); + }, + ); + }); }); |