diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-17 11:59:07 +0000 |
commit | 8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca (patch) | |
tree | 544930fb309b30317ae9797a9683768705d664c4 /spec/frontend/registry/settings/components | |
parent | 4b1de649d0168371549608993deac953eb692019 (diff) | |
download | gitlab-ce-8b573c94895dc0ac0e1d9d59cf3e8745e8b539ca.tar.gz |
Add latest changes from gitlab-org/gitlab@13-7-stable-eev13.7.0-rc42
Diffstat (limited to 'spec/frontend/registry/settings/components')
7 files changed, 630 insertions, 53 deletions
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 new file mode 100644 index 00000000000..d7f89ce070e --- /dev/null +++ b/spec/frontend/registry/settings/components/__snapshots__/settings_form_spec.js.snap @@ -0,0 +1,64 @@ +// 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}More information%{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}More information%{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 new file mode 100644 index 00000000000..e0cac317ad6 --- /dev/null +++ b/spec/frontend/registry/settings/components/expiration_dropdown_spec.js @@ -0,0 +1,83 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlFormGroup, GlFormSelect } from 'jest/registry/shared/stubs'; +import component from '~/registry/settings/components/expiration_dropdown.vue'; + +describe('ExpirationDropdown', () => { + let wrapper; + + const defaultProps = { + name: 'foo', + label: 'label-bar', + formOptions: [{ key: 'foo', label: 'bar' }, { key: 'baz', label: 'zab' }], + }; + + const findFormSelect = () => wrapper.find(GlFormSelect); + const findFormGroup = () => wrapper.find(GlFormGroup); + const findOptions = () => wrapper.findAll('[data-testid="option"]'); + + const mountComponent = props => { + wrapper = shallowMount(component, { + stubs: { + GlFormGroup, + GlFormSelect, + }, + propsData: { + ...defaultProps, + ...props, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('structure', () => { + it('has a form-select component', () => { + mountComponent(); + expect(findFormSelect().exists()).toBe(true); + }); + + it('has the correct options', () => { + mountComponent(); + + expect(findOptions()).toHaveLength(defaultProps.formOptions.length); + }); + }); + + describe('model', () => { + it('assign the right props to the form-select component', () => { + const value = 'foobar'; + const disabled = true; + + mountComponent({ value, disabled }); + + expect(findFormSelect().props()).toMatchObject({ + value, + disabled, + }); + expect(findFormSelect().attributes('id')).toBe(defaultProps.name); + }); + + it('assign the right props to the form-group component', () => { + mountComponent(); + + expect(findFormGroup().attributes()).toMatchObject({ + id: `${defaultProps.name}-form-group`, + 'label-for': defaultProps.name, + label: defaultProps.label, + }); + }); + + it('emits input event when form-select emits input', () => { + const emittedValue = 'barfoo'; + + mountComponent(); + + findFormSelect().vm.$emit('input', emittedValue); + + expect(wrapper.emitted('input')).toEqual([[emittedValue]]); + }); + }); +}); diff --git a/spec/frontend/registry/settings/components/expiration_input_spec.js b/spec/frontend/registry/settings/components/expiration_input_spec.js new file mode 100644 index 00000000000..849f85aa265 --- /dev/null +++ b/spec/frontend/registry/settings/components/expiration_input_spec.js @@ -0,0 +1,169 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlSprintf, GlFormInput, GlLink } from '@gitlab/ui'; +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 new file mode 100644 index 00000000000..c594b1f449d --- /dev/null +++ b/spec/frontend/registry/settings/components/expiration_run_text_spec.js @@ -0,0 +1,62 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlFormInput } from '@gitlab/ui'; +import { GlFormGroup } from 'jest/registry/shared/stubs'; +import component from '~/registry/settings/components/expiration_run_text.vue'; +import { NEXT_CLEANUP_LABEL, NOT_SCHEDULED_POLICY_TEXT } from '~/registry/settings/constants'; + +describe('ExpirationToggle', () => { + let wrapper; + const value = 'foo'; + + const findInput = () => wrapper.find(GlFormInput); + const findFormGroup = () => wrapper.find(GlFormGroup); + + const mountComponent = propsData => { + wrapper = shallowMount(component, { + stubs: { + GlFormGroup, + }, + propsData, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + describe('structure', () => { + it('has an input component', () => { + mountComponent(); + + expect(findInput().exists()).toBe(true); + }); + }); + + describe('model', () => { + it('assigns the right props to the 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 new file mode 100644 index 00000000000..99ff7a7f77a --- /dev/null +++ b/spec/frontend/registry/settings/components/expiration_toggle_spec.js @@ -0,0 +1,77 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlToggle, GlSprintf } from '@gitlab/ui'; +import { GlFormGroup } from 'jest/registry/shared/stubs'; +import component from '~/registry/settings/components/expiration_toggle.vue'; +import { + 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().exists()).toBe(true); + }); + + 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 index a784396f47a..c31c7bdf99b 100644 --- a/spec/frontend/registry/settings/components/registry_settings_app_spec.js +++ b/spec/frontend/registry/settings/components/registry_settings_app_spec.js @@ -3,15 +3,19 @@ import VueApollo from 'vue-apollo'; 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 expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.graphql'; +import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.query.graphql'; import SettingsForm from '~/registry/settings/components/settings_form.vue'; -import { FETCH_SETTINGS_ERROR_MESSAGE } from '~/registry/shared/constants'; import { + FETCH_SETTINGS_ERROR_MESSAGE, UNAVAILABLE_FEATURE_INTRO_TEXT, UNAVAILABLE_USER_FEATURE_TEXT, } from '~/registry/settings/constants'; -import { expirationPolicyPayload, emptyExpirationPolicyPayload } from '../mock_data'; +import { + expirationPolicyPayload, + emptyExpirationPolicyPayload, + containerExpirationPolicyData, +} from '../mock_data'; const localVue = createLocalVue(); @@ -62,6 +66,29 @@ describe('Registry Settings App', () => { 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()), diff --git a/spec/frontend/registry/settings/components/settings_form_spec.js b/spec/frontend/registry/settings/components/settings_form_spec.js index 4346cfadcc8..b89269c0ae4 100644 --- a/spec/frontend/registry/settings/components/settings_form_spec.js +++ b/spec/frontend/registry/settings/components/settings_form_spec.js @@ -4,13 +4,12 @@ import createMockApollo from 'jest/helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import Tracking from '~/tracking'; import component from '~/registry/settings/components/settings_form.vue'; -import expirationPolicyFields from '~/registry/shared/components/expiration_policy_fields.vue'; -import updateContainerExpirationPolicyMutation from '~/registry/settings/graphql/mutations/update_container_expiration_policy.graphql'; -import expirationPolicyQuery from '~/registry/settings/graphql/queries/get_expiration_policy.graphql'; +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 { UPDATE_SETTINGS_ERROR_MESSAGE, UPDATE_SETTINGS_SUCCESS_MESSAGE, -} from '~/registry/shared/constants'; +} from '~/registry/settings/constants'; import { GlCard, GlLoadingIcon } from '../../shared/stubs'; import { expirationPolicyPayload, expirationPolicyMutationPayload } from '../mock_data'; @@ -39,9 +38,15 @@ describe('Settings Form', () => { }; const findForm = () => wrapper.find({ ref: 'form-element' }); - const findFields = () => wrapper.find(expirationPolicyFields); - const findCancelButton = () => wrapper.find({ ref: 'cancel-button' }); - const findSaveButton = () => wrapper.find({ ref: 'save-button' }); + + 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, @@ -109,45 +114,136 @@ describe('Settings Form', () => { wrapper.destroy(); }); - describe('data binding', () => { - it('v-model change update the settings property', () => { + 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(); - findFields().vm.$emit('input', { newValue: 'foo' }); - expect(wrapper.emitted('input')).toEqual([['foo']]); + + expect(finder().element).toMatchSnapshot(); }); - it('v-model change update the api error property', () => { - const apiErrors = { baz: 'bar' }; - mountComponent({ data: { apiErrors } }); - expect(findFields().props('apiErrors')).toEqual(apiErrors); - findFields().vm.$emit('input', { newValue: 'foo', modified: 'baz' }); - expect(findFields().props('apiErrors')).toEqual({}); + 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(findFields().props('value')).toEqual({ - cadence: 'EVERY_DAY', - keepN: 'TEN_TAGS', - olderThan: 'NINETY_DAYS', - }); + 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', () => { - beforeEach(() => { + it('calls the appropriate function', () => { mountComponent(); findForm().trigger('reset'); - }); - it('calls the appropriate function', () => { + 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 ', () => { @@ -209,6 +305,7 @@ describe('Settings Form', () => { }); }); }); + describe('global errors', () => { it('shows an error', async () => { const handlers = mountComponentWithApollo({ @@ -230,7 +327,7 @@ describe('Settings Form', () => { graphQLErrors: [ { extensions: { - problems: [{ path: ['name'], message: 'baz' }], + problems: [{ path: ['nameRegexKeep'], message: 'baz' }], }, }, ], @@ -241,7 +338,7 @@ describe('Settings Form', () => { await waitForPromises(); await wrapper.vm.$nextTick(); - expect(findFields().props('apiErrors')).toEqual({ name: 'baz' }); + expect(findKeepRegexInput().props('error')).toEqual('baz'); }); }); }); @@ -257,23 +354,21 @@ describe('Settings Form', () => { }); it.each` - isLoading | isEdited | mutationLoading | isDisabled - ${true} | ${true} | ${true} | ${true} - ${false} | ${true} | ${true} | ${true} - ${false} | ${false} | ${true} | ${true} - ${true} | ${false} | ${false} | ${true} - ${false} | ${false} | ${false} | ${true} - ${false} | ${true} | ${false} | ${false} + isLoading | isEdited | mutationLoading + ${true} | ${true} | ${true} + ${false} | ${true} | ${true} + ${false} | ${false} | ${true} + ${true} | ${false} | ${false} + ${false} | ${false} | ${false} `( - 'when isLoading is $isLoading and isEdited is $isEdited and mutationLoading is $mutationLoading is $isDisabled that the is disabled', - ({ isEdited, isLoading, mutationLoading, isDisabled }) => { + 'when isLoading is $isLoading, isEdited is $isEdited and mutationLoading is $mutationLoading is disabled', + ({ isEdited, isLoading, mutationLoading }) => { mountComponent({ props: { ...defaultProps, isEdited, isLoading }, data: { mutationLoading }, }); - const expectation = isDisabled ? 'true' : undefined; - expect(findCancelButton().attributes('disabled')).toBe(expectation); + expect(findCancelButton().props('disabled')).toBe(true); }, ); }); @@ -284,24 +379,24 @@ describe('Settings Form', () => { expect(findSaveButton().attributes('type')).toBe('submit'); }); + it.each` - isLoading | fieldsAreValid | mutationLoading | isDisabled - ${true} | ${true} | ${true} | ${true} - ${false} | ${true} | ${true} | ${true} - ${false} | ${false} | ${true} | ${true} - ${true} | ${false} | ${false} | ${true} - ${false} | ${false} | ${false} | ${true} - ${false} | ${true} | ${false} | ${false} + 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 and fieldsAreValid is $fieldsAreValid and mutationLoading is $mutationLoading is $isDisabled that the is disabled', - ({ fieldsAreValid, isLoading, mutationLoading, isDisabled }) => { + 'when isLoading is $isLoading, localErrors is $localErrors and mutationLoading is $mutationLoading is disabled', + ({ localErrors, isLoading, mutationLoading }) => { mountComponent({ props: { ...defaultProps, isLoading }, - data: { mutationLoading, fieldsAreValid }, + data: { mutationLoading, localErrors }, }); - const expectation = isDisabled ? 'true' : undefined; - expect(findSaveButton().attributes('disabled')).toBe(expectation); + expect(findSaveButton().props('disabled')).toBe(true); }, ); |