diff options
Diffstat (limited to 'spec/frontend/jobs/components/job/manual_variables_form_spec.js')
-rw-r--r-- | spec/frontend/jobs/components/job/manual_variables_form_spec.js | 232 |
1 files changed, 148 insertions, 84 deletions
diff --git a/spec/frontend/jobs/components/job/manual_variables_form_spec.js b/spec/frontend/jobs/components/job/manual_variables_form_spec.js index 5806f9f75f9..45a1e9dca76 100644 --- a/spec/frontend/jobs/components/job/manual_variables_form_spec.js +++ b/spec/frontend/jobs/components/job/manual_variables_form_spec.js @@ -1,46 +1,71 @@ import { GlSprintf, GlLink } from '@gitlab/ui'; -import { mount } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; -import Vuex from 'vuex'; -import { extendedWrapper } from 'helpers/vue_test_utils_helper'; +import { createLocalVue } from '@vue/test-utils'; +import VueApollo from 'vue-apollo'; +import { nextTick } from 'vue'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import { convertToGraphQLId } from '~/graphql_shared/utils'; +import { GRAPHQL_ID_TYPES } from '~/jobs/constants'; +import waitForPromises from 'helpers/wait_for_promises'; import ManualVariablesForm from '~/jobs/components/job/manual_variables_form.vue'; - -Vue.use(Vuex); +import getJobQuery from '~/jobs/components/job/graphql/queries/get_job.query.graphql'; +import retryJobMutation from '~/jobs/components/job/graphql/mutations/job_retry_with_variables.mutation.graphql'; +import { + mockFullPath, + mockId, + mockJobResponse, + mockJobWithVariablesResponse, + mockJobMutationData, +} from './mock_data'; + +const localVue = createLocalVue(); +localVue.use(VueApollo); + +const defaultProvide = { + projectPath: mockFullPath, +}; describe('Manual Variables Form', () => { let wrapper; - let store; - - const requiredProps = { - action: { - path: '/play', - method: 'post', - button_title: 'Trigger this manual action', - }, + let mockApollo; + let getJobQueryResponse; + + const createComponent = ({ options = {}, props = {} } = {}) => { + wrapper = mountExtended(ManualVariablesForm, { + propsData: { + ...props, + jobId: mockId, + isRetryable: true, + }, + provide: { + ...defaultProvide, + }, + ...options, + }); }; - const createComponent = (props = {}) => { - store = new Vuex.Store({ - actions: { - triggerManualJob: jest.fn(), - }, + const createComponentWithApollo = async ({ props = {} } = {}) => { + const requestHandlers = [[getJobQuery, getJobQueryResponse]]; + + mockApollo = createMockApollo(requestHandlers); + + const options = { + localVue, + apolloProvider: mockApollo, + }; + + createComponent({ + props, + options, }); - wrapper = extendedWrapper( - mount(ManualVariablesForm, { - propsData: { ...requiredProps, ...props }, - store, - stubs: { - GlSprintf, - }, - }), - ); + return waitForPromises(); }; const findHelpText = () => wrapper.findComponent(GlSprintf); const findHelpLink = () => wrapper.findComponent(GlLink); - - const findTriggerBtn = () => wrapper.findByTestId('trigger-manual-job-btn'); + const findCancelBtn = () => wrapper.findByTestId('cancel-btn'); + const findRerunBtn = () => wrapper.findByTestId('run-manual-job-btn'); const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn'); const findAllDeleteVarBtns = () => wrapper.findAllByTestId('delete-variable-btn'); const findDeleteVarBtnPlaceholder = () => wrapper.findByTestId('delete-variable-btn-placeholder'); @@ -62,95 +87,134 @@ describe('Manual Variables Form', () => { }; beforeEach(() => { - createComponent(); + getJobQueryResponse = jest.fn(); }); afterEach(() => { wrapper.destroy(); }); - it('creates a new variable when user enters a new key value', async () => { - expect(findAllVariables()).toHaveLength(1); + describe('when page renders', () => { + beforeEach(async () => { + getJobQueryResponse.mockResolvedValue(mockJobResponse); + await createComponentWithApollo(); + }); + + it('renders help text with provided link', () => { + expect(findHelpText().exists()).toBe(true); + expect(findHelpLink().attributes('href')).toBe( + '/help/ci/variables/index#add-a-cicd-variable-to-a-project', + ); + }); + + it('renders buttons', () => { + expect(findCancelBtn().exists()).toBe(true); + expect(findRerunBtn().exists()).toBe(true); + }); + }); + + describe('when job has variables', () => { + beforeEach(async () => { + getJobQueryResponse.mockResolvedValue(mockJobWithVariablesResponse); + await createComponentWithApollo(); + }); - await setCiVariableKey(); + it('sets manual job variables', () => { + const queryKey = mockJobWithVariablesResponse.data.project.job.manualVariables.nodes[0].key; + const queryValue = + mockJobWithVariablesResponse.data.project.job.manualVariables.nodes[0].value; - expect(findAllVariables()).toHaveLength(2); + expect(findCiVariableKey().element.value).toBe(queryKey); + expect(findCiVariableValue().element.value).toBe(queryValue); + }); }); - it('does not create extra empty variables', async () => { - expect(findAllVariables()).toHaveLength(1); + describe('when mutation fires', () => { + beforeEach(async () => { + await createComponentWithApollo(); + jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockJobMutationData); + }); - await setCiVariableKey(); + it('passes variables in correct format', async () => { + await setCiVariableKey(); - expect(findAllVariables()).toHaveLength(2); + await findCiVariableValue().setValue('new value'); - await setCiVariableKey(); + await findRerunBtn().vm.$emit('click'); - expect(findAllVariables()).toHaveLength(2); + expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1); + expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({ + mutation: retryJobMutation, + variables: { + id: convertToGraphQLId(GRAPHQL_ID_TYPES.ciBuild, mockId), + variables: [ + { + key: 'new key', + value: 'new value', + }, + ], + }, + }); + }); }); - it('removes the correct variable row', async () => { - const variableKeyNameOne = 'key-one'; - const variableKeyNameThree = 'key-three'; + describe('updating variables in UI', () => { + beforeEach(async () => { + getJobQueryResponse.mockResolvedValue(mockJobResponse); + await createComponentWithApollo(); + }); - await setCiVariableKeyByPosition(0, variableKeyNameOne); + it('creates a new variable when user enters a new key value', async () => { + expect(findAllVariables()).toHaveLength(1); - await setCiVariableKeyByPosition(1, 'key-two'); + await setCiVariableKey(); - await setCiVariableKeyByPosition(2, variableKeyNameThree); + expect(findAllVariables()).toHaveLength(2); + }); - expect(findAllVariables()).toHaveLength(4); + it('does not create extra empty variables', async () => { + expect(findAllVariables()).toHaveLength(1); - await findAllDeleteVarBtns().at(1).trigger('click'); + await setCiVariableKey(); - expect(findAllVariables()).toHaveLength(3); + expect(findAllVariables()).toHaveLength(2); - expect(findAllCiVariableKeys().at(0).element.value).toBe(variableKeyNameOne); - expect(findAllCiVariableKeys().at(1).element.value).toBe(variableKeyNameThree); - expect(findAllCiVariableKeys().at(2).element.value).toBe(''); - }); + await setCiVariableKey(); - it('trigger button is disabled after trigger action', async () => { - expect(findTriggerBtn().props('disabled')).toBe(false); + expect(findAllVariables()).toHaveLength(2); + }); - await findTriggerBtn().trigger('click'); + it('removes the correct variable row', async () => { + const variableKeyNameOne = 'key-one'; + const variableKeyNameThree = 'key-three'; - expect(findTriggerBtn().props('disabled')).toBe(true); - }); + await setCiVariableKeyByPosition(0, variableKeyNameOne); - it('delete variable button should only show when there is more than one variable', async () => { - expect(findDeleteVarBtn().exists()).toBe(false); + await setCiVariableKeyByPosition(1, 'key-two'); - await setCiVariableKey(); + await setCiVariableKeyByPosition(2, variableKeyNameThree); - expect(findDeleteVarBtn().exists()).toBe(true); - }); + expect(findAllVariables()).toHaveLength(4); - it('delete variable button placeholder should only exist when a user cannot remove', async () => { - expect(findDeleteVarBtnPlaceholder().exists()).toBe(true); - }); + await findAllDeleteVarBtns().at(1).trigger('click'); - it('renders help text with provided link', () => { - expect(findHelpText().exists()).toBe(true); - expect(findHelpLink().attributes('href')).toBe( - '/help/ci/variables/index#add-a-cicd-variable-to-a-project', - ); - }); + expect(findAllVariables()).toHaveLength(3); - it('passes variables in correct format', async () => { - jest.spyOn(store, 'dispatch'); + expect(findAllCiVariableKeys().at(0).element.value).toBe(variableKeyNameOne); + expect(findAllCiVariableKeys().at(1).element.value).toBe(variableKeyNameThree); + expect(findAllCiVariableKeys().at(2).element.value).toBe(''); + }); - await setCiVariableKey(); + it('delete variable button should only show when there is more than one variable', async () => { + expect(findDeleteVarBtn().exists()).toBe(false); - await findCiVariableValue().setValue('new value'); + await setCiVariableKey(); - await findTriggerBtn().trigger('click'); + expect(findDeleteVarBtn().exists()).toBe(true); + }); - expect(store.dispatch).toHaveBeenCalledWith('triggerManualJob', [ - { - key: 'new key', - secret_value: 'new value', - }, - ]); + it('delete variable button placeholder should only exist when a user cannot remove', async () => { + expect(findDeleteVarBtnPlaceholder().exists()).toBe(true); + }); }); }); |