debian-mirror-gitlab/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
2020-06-23 00:09:42 +05:30

280 lines
8.6 KiB
JavaScript

import Vuex from 'vuex';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import { GlDeprecatedButton } from '@gitlab/ui';
import { AWS_ACCESS_KEY_ID } from '~/ci_variable_list/constants';
import CiVariableModal from '~/ci_variable_list/components/ci_variable_modal.vue';
import CiKeyField from '~/ci_variable_list/components/ci_key_field.vue';
import { awsTokens } from '~/ci_variable_list/components/ci_variable_autocomplete_tokens';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
import ModalStub from '../stubs';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Ci variable modal', () => {
let wrapper;
let store;
const createComponent = (method, options = {}) => {
store = createStore();
wrapper = method(CiVariableModal, {
attachToDocument: true,
provide: { glFeatures: { ciKeyAutocomplete: true } },
stubs: {
GlModal: ModalStub,
},
localVue,
store,
...options,
});
};
const findModal = () => wrapper.find(ModalStub);
const addOrUpdateButton = index =>
findModal()
.findAll(GlDeprecatedButton)
.at(index);
const deleteVariableButton = () =>
findModal()
.findAll(GlDeprecatedButton)
.at(1);
afterEach(() => {
wrapper.destroy();
});
describe('Feature flag', () => {
describe('when off', () => {
beforeEach(() => {
createComponent(shallowMount, { provide: { glFeatures: { ciKeyAutocomplete: false } } });
});
it('does not render the autocomplete dropdown', () => {
expect(wrapper.contains(CiKeyField)).toBe(false);
});
});
describe('when on', () => {
beforeEach(() => {
createComponent(shallowMount);
});
it('renders the autocomplete dropdown', () => {
expect(wrapper.find(CiKeyField).exists()).toBe(true);
});
});
});
describe('Basic interactions', () => {
beforeEach(() => {
createComponent(shallowMount);
});
it('button is disabled when no key/value pair are present', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeTruthy();
});
});
describe('Adding a new variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
createComponent(shallowMount);
jest.spyOn(store, 'dispatch').mockImplementation();
store.state.variable = variable;
});
it('button is enabled when key/value pair are present', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeFalsy();
});
it('Add variable button dispatches addVariable action', () => {
addOrUpdateButton(1).vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith('addVariable');
});
it('Clears the modal state once modal is hidden', () => {
findModal().vm.$emit('hidden');
expect(store.dispatch).toHaveBeenCalledWith('clearModal');
});
it('should dispatch setVariableProtected when admin settings are configured to protect variables', () => {
store.state.isProtectedByDefault = true;
findModal().vm.$emit('shown');
expect(store.dispatch).toHaveBeenCalledWith('setVariableProtected');
});
});
describe('Adding a new non-AWS variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: 'key',
value: 'value',
secret_value: 'secret_value',
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
});
it('does not show AWS guidance tip', () => {
const tip = wrapper.find(`div[data-testid='aws-guidance-tip']`);
expect(tip.exists()).toBe(true);
expect(tip.isVisible()).toBe(false);
});
});
describe('Adding a new AWS variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: AWS_ACCESS_KEY_ID,
value: 'AKIAIOSFODNN7EXAMPLEjdhy',
secret_value: 'AKIAIOSFODNN7EXAMPLEjdhy',
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
});
it('shows AWS guidance tip', () => {
const tip = wrapper.find(`[data-testid='aws-guidance-tip']`);
expect(tip.exists()).toBe(true);
expect(tip.isVisible()).toBe(true);
});
});
describe('Editing a variable', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
createComponent(shallowMount);
jest.spyOn(store, 'dispatch').mockImplementation();
store.state.variableBeingEdited = variable;
});
it('button text is Update variable when updating', () => {
expect(addOrUpdateButton(2).text()).toBe('Update variable');
});
it('Update variable button dispatches updateVariable with correct variable', () => {
addOrUpdateButton(2).vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith(
'updateVariable',
store.state.variableBeingEdited,
);
});
it('Resets the editing state once modal is hidden', () => {
findModal().vm.$emit('hidden');
expect(store.dispatch).toHaveBeenCalledWith('resetEditing');
});
it('dispatches deleteVariable with correct variable to delete', () => {
deleteVariableButton().vm.$emit('click');
expect(store.dispatch).toHaveBeenCalledWith('deleteVariable', mockData.mockVariables[0]);
});
});
describe('Validations', () => {
const maskError = 'This variable can not be masked.';
describe('when the key state is invalid', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidKeyVariable = {
...variable,
key: AWS_ACCESS_KEY_ID,
value: 'AKIAIOSFODNN7EXAMPLEjdhy',
secret_value: 'AKIAIOSFODNN7EXAMPLEjdhy',
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
});
it('disables the submit button', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeTruthy();
});
it('shows the correct error text', () => {
const errorText = awsTokens[AWS_ACCESS_KEY_ID].invalidMessage;
expect(findModal().text()).toContain(errorText);
});
});
describe('when the mask state is invalid', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidMaskVariable = {
...variable,
key: 'qs',
value: 'd:;',
secret_value: 'd:;',
masked: true,
};
createComponent(mount);
store.state.variable = invalidMaskVariable;
});
it('disables the submit button', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeTruthy();
});
it('shows the correct error text', () => {
expect(findModal().text()).toContain(maskError);
});
});
describe('when the mask and key states are invalid', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const invalidMaskandKeyVariable = {
...variable,
key: AWS_ACCESS_KEY_ID,
value: 'AKIAIOSFODNN7EXAMPLEjdhyd:;',
secret_value: 'AKIAIOSFODNN7EXAMPLEjdhyd:;',
masked: true,
};
createComponent(mount);
store.state.variable = invalidMaskandKeyVariable;
});
it('disables the submit button', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeTruthy();
});
it('shows the correct error text', () => {
const errorText = awsTokens[AWS_ACCESS_KEY_ID].invalidMessage;
expect(findModal().text()).toContain(maskError);
expect(findModal().text()).toContain(errorText);
});
});
describe('when both states are valid', () => {
beforeEach(() => {
const [variable] = mockData.mockVariables;
const validMaskandKeyVariable = {
...variable,
key: AWS_ACCESS_KEY_ID,
value: 'AKIAIOSFODNN7EXAMPLE',
secret_value: 'AKIAIOSFODNN7EXAMPLE',
masked: true,
};
createComponent(mount);
store.state.variable = validMaskandKeyVariable;
store.state.maskableRegex = /^[a-zA-Z0-9_+=/@:-]{8,}$/;
});
it('does not disable the submit button', () => {
expect(addOrUpdateButton(1).attributes('disabled')).toBeFalsy();
});
it('shows no error text', () => {
const errorText = awsTokens[AWS_ACCESS_KEY_ID].invalidMessage;
expect(findModal().text()).not.toContain(maskError);
expect(findModal().text()).not.toContain(errorText);
});
});
});
});