Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/ci_variable_list')
-rw-r--r--spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js175
-rw-r--r--spec/frontend/ci_variable_list/components/ci_group_variables_spec.js181
-rw-r--r--spec/frontend/ci_variable_list/components/ci_project_variables_spec.js202
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js90
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js48
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_shared_spec.js428
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_environments_dropdown_spec.js119
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js323
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js38
-rw-r--r--spec/frontend/ci_variable_list/components/legacy_ci_variable_table_spec.js86
-rw-r--r--spec/frontend/ci_variable_list/mocks.js77
-rw-r--r--spec/frontend/ci_variable_list/store/actions_spec.js319
-rw-r--r--spec/frontend/ci_variable_list/store/getters_spec.js21
-rw-r--r--spec/frontend/ci_variable_list/store/mutations_spec.js136
-rw-r--r--spec/frontend/ci_variable_list/store/utils_spec.js49
16 files changed, 642 insertions, 1652 deletions
diff --git a/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
index 864041141b8..c7375acd8e5 100644
--- a/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_admin_variables_spec.js
@@ -1,178 +1,35 @@
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/settings';
import ciAdminVariables from '~/ci_variable_list/components/ci_admin_variables.vue';
-import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
-import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
-import getAdminVariables from '~/ci_variable_list/graphql/queries/variables.query.graphql';
+import ciVariableShared from '~/ci_variable_list/components/ci_variable_shared.vue';
-import addAdminVariable from '~/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql';
-import deleteAdminVariable from '~/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql';
-import updateAdminVariable from '~/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql';
-
-import { genericMutationErrorText, variableFetchErrorText } from '~/ci_variable_list/constants';
-
-import { mockAdminVariables, newVariable } from '../mocks';
-
-jest.mock('~/flash');
-
-Vue.use(VueApollo);
-
-const mockProvide = {
- endpoint: '/variables',
-};
-
-describe('Ci Admin Variable list', () => {
+describe('Ci Project Variable wrapper', () => {
let wrapper;
- let mockApollo;
- let mockVariables;
-
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findCiTable = () => wrapper.findComponent(GlTable);
- const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
-
- // eslint-disable-next-line consistent-return
- const createComponentWithApollo = async ({ isLoading = false } = {}) => {
- const handlers = [[getAdminVariables, mockVariables]];
-
- mockApollo = createMockApollo(handlers, resolvers);
+ const findCiShared = () => wrapper.findComponent(ciVariableShared);
- wrapper = shallowMount(ciAdminVariables, {
- provide: mockProvide,
- apolloProvider: mockApollo,
- stubs: { ciVariableSettings, ciVariableTable },
- });
-
- if (!isLoading) {
- return waitForPromises();
- }
+ const createComponent = () => {
+ wrapper = shallowMount(ciAdminVariables);
};
beforeEach(() => {
- mockVariables = jest.fn();
+ createComponent();
});
afterEach(() => {
wrapper.destroy();
});
- describe('while queries are being fetch', () => {
- beforeEach(() => {
- createComponentWithApollo({ isLoading: true });
- });
-
- it('shows a loading icon', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findCiTable().exists()).toBe(false);
+ it('Passes down the correct props to ci_variable_shared', () => {
+ expect(findCiShared().props()).toEqual({
+ areScopedVariablesAvailable: false,
+ componentName: 'InstanceVariables',
+ hideEnvironmentScope: true,
+ mutationData: wrapper.vm.$options.mutationData,
+ queryData: wrapper.vm.$options.queryData,
+ refetchAfterMutation: true,
+ fullPath: null,
+ id: null,
});
});
-
- describe('when queries are resolved', () => {
- describe('successfuly', () => {
- beforeEach(async () => {
- mockVariables.mockResolvedValue(mockAdminVariables);
-
- await createComponentWithApollo();
- });
-
- it('passes down the expected environments as props', () => {
- expect(findCiSettings().props('environments')).toEqual([]);
- });
-
- it('passes down the expected variables as props', () => {
- expect(findCiSettings().props('variables')).toEqual(
- mockAdminVariables.data.ciVariables.nodes,
- );
- });
-
- it('createAlert was not called', () => {
- expect(createAlert).not.toHaveBeenCalled();
- });
- });
-
- describe('with an error for variables', () => {
- beforeEach(async () => {
- mockVariables.mockRejectedValue();
-
- await createComponentWithApollo();
- });
-
- it('calls createAlert with the expected error message', () => {
- expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
- });
- });
- });
-
- describe('mutations', () => {
- beforeEach(async () => {
- mockVariables.mockResolvedValue(mockAdminVariables);
-
- await createComponentWithApollo();
- });
- it.each`
- actionName | mutation | event
- ${'add'} | ${addAdminVariable} | ${'add-variable'}
- ${'update'} | ${updateAdminVariable} | ${'update-variable'}
- ${'delete'} | ${deleteAdminVariable} | ${'delete-variable'}
- `(
- 'calls the right mutation when user performs $actionName variable',
- async ({ event, mutation }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation,
- variables: {
- endpoint: mockProvide.endpoint,
- variable: newVariable,
- },
- });
- },
- );
-
- it.each`
- actionName | event | mutationName
- ${'add'} | ${'add-variable'} | ${'addAdminVariable'}
- ${'update'} | ${'update-variable'} | ${'updateAdminVariable'}
- ${'delete'} | ${'delete-variable'} | ${'deleteAdminVariable'}
- `(
- 'throws with the specific graphql error if present when user performs $actionName variable',
- async ({ event, mutationName }) => {
- const graphQLErrorMessage = 'There is a problem with this graphQL action';
- jest
- .spyOn(wrapper.vm.$apollo, 'mutate')
- .mockResolvedValue({ data: { [mutationName]: { errors: [graphQLErrorMessage] } } });
- await findCiSettings().vm.$emit(event, newVariable);
- await nextTick();
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
- },
- );
-
- it.each`
- actionName | event
- ${'add'} | ${'add-variable'}
- ${'update'} | ${'update-variable'}
- ${'delete'} | ${'delete-variable'}
- `(
- 'throws generic error when the mutation fails with no graphql errors and user performs $actionName variable',
- async ({ event }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
- throw new Error();
- });
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
- },
- );
- });
});
diff --git a/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
index 8a48e73eb9f..ef5a86ccb61 100644
--- a/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_group_variables_spec.js
@@ -1,183 +1,72 @@
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/settings';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import ciGroupVariables from '~/ci_variable_list/components/ci_group_variables.vue';
-import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
-import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
-import getGroupVariables from '~/ci_variable_list/graphql/queries/group_variables.query.graphql';
+import ciVariableShared from '~/ci_variable_list/components/ci_variable_shared.vue';
-import addGroupVariable from '~/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql';
-import deleteGroupVariable from '~/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql';
-import updateGroupVariable from '~/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql';
-
-import { genericMutationErrorText, variableFetchErrorText } from '~/ci_variable_list/constants';
-
-import { mockGroupVariables, newVariable } from '../mocks';
-
-jest.mock('~/flash');
-
-Vue.use(VueApollo);
+import { GRAPHQL_GROUP_TYPE } from '~/ci_variable_list/constants';
const mockProvide = {
- endpoint: '/variables',
- groupPath: '/namespace/group',
- groupId: 1,
+ glFeatures: {
+ groupScopedCiVariables: false,
+ },
+ groupPath: '/group',
+ groupId: 12,
};
-describe('Ci Group Variable list', () => {
+describe('Ci Group Variable wrapper', () => {
let wrapper;
- let mockApollo;
- let mockVariables;
-
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findCiTable = () => wrapper.findComponent(GlTable);
- const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
-
- // eslint-disable-next-line consistent-return
- const createComponentWithApollo = async ({ isLoading = false } = {}) => {
- const handlers = [[getGroupVariables, mockVariables]];
-
- mockApollo = createMockApollo(handlers, resolvers);
+ const findCiShared = () => wrapper.findComponent(ciVariableShared);
+ const createComponent = ({ provide = {} } = {}) => {
wrapper = shallowMount(ciGroupVariables, {
- provide: mockProvide,
- apolloProvider: mockApollo,
- stubs: { ciVariableSettings, ciVariableTable },
+ provide: { ...mockProvide, ...provide },
});
-
- if (!isLoading) {
- return waitForPromises();
- }
};
- beforeEach(() => {
- mockVariables = jest.fn();
- });
-
afterEach(() => {
wrapper.destroy();
});
- describe('while queries are being fetch', () => {
+ describe('Props', () => {
beforeEach(() => {
- createComponentWithApollo({ isLoading: true });
+ createComponent();
});
- it('shows a loading icon', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findCiTable().exists()).toBe(false);
+ it('are passed down the correctly to ci_variable_shared', () => {
+ expect(findCiShared().props()).toEqual({
+ id: convertToGraphQLId(GRAPHQL_GROUP_TYPE, mockProvide.groupId),
+ areScopedVariablesAvailable: false,
+ componentName: 'GroupVariables',
+ fullPath: mockProvide.groupPath,
+ hideEnvironmentScope: false,
+ mutationData: wrapper.vm.$options.mutationData,
+ queryData: wrapper.vm.$options.queryData,
+ refetchAfterMutation: false,
+ });
});
});
- describe('when queries are resolved', () => {
- describe('successfuly', () => {
- beforeEach(async () => {
- mockVariables.mockResolvedValue(mockGroupVariables);
-
- await createComponentWithApollo();
- });
-
- it('passes down the expected environments as props', () => {
- expect(findCiSettings().props('environments')).toEqual([]);
- });
-
- it('passes down the expected variables as props', () => {
- expect(findCiSettings().props('variables')).toEqual(
- mockGroupVariables.data.group.ciVariables.nodes,
- );
+ describe('feature flag', () => {
+ describe('When enabled', () => {
+ beforeEach(() => {
+ createComponent({ provide: { glFeatures: { groupScopedCiVariables: true } } });
});
- it('createAlert was not called', () => {
- expect(createAlert).not.toHaveBeenCalled();
+ it('Passes down `true` to variable shared component', () => {
+ expect(findCiShared().props('areScopedVariablesAvailable')).toBe(true);
});
});
- describe('with an error for variables', () => {
- beforeEach(async () => {
- mockVariables.mockRejectedValue();
-
- await createComponentWithApollo();
+ describe('When disabled', () => {
+ beforeEach(() => {
+ createComponent({ provide: { glFeatures: { groupScopedCiVariables: false } } });
});
- it('calls createAlert with the expected error message', () => {
- expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ it('Passes down `false` to variable shared component', () => {
+ expect(findCiShared().props('areScopedVariablesAvailable')).toBe(false);
});
});
});
-
- describe('mutations', () => {
- beforeEach(async () => {
- mockVariables.mockResolvedValue(mockGroupVariables);
-
- await createComponentWithApollo();
- });
- it.each`
- actionName | mutation | event
- ${'add'} | ${addGroupVariable} | ${'add-variable'}
- ${'update'} | ${updateGroupVariable} | ${'update-variable'}
- ${'delete'} | ${deleteGroupVariable} | ${'delete-variable'}
- `(
- 'calls the right mutation when user performs $actionName variable',
- async ({ event, mutation }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation,
- variables: {
- endpoint: mockProvide.endpoint,
- fullPath: mockProvide.groupPath,
- groupId: convertToGraphQLId('Group', mockProvide.groupId),
- variable: newVariable,
- },
- });
- },
- );
-
- it.each`
- actionName | event | mutationName
- ${'add'} | ${'add-variable'} | ${'addGroupVariable'}
- ${'update'} | ${'update-variable'} | ${'updateGroupVariable'}
- ${'delete'} | ${'delete-variable'} | ${'deleteGroupVariable'}
- `(
- 'throws with the specific graphql error if present when user performs $actionName variable',
- async ({ event, mutationName }) => {
- const graphQLErrorMessage = 'There is a problem with this graphQL action';
- jest
- .spyOn(wrapper.vm.$apollo, 'mutate')
- .mockResolvedValue({ data: { [mutationName]: { errors: [graphQLErrorMessage] } } });
- await findCiSettings().vm.$emit(event, newVariable);
- await nextTick();
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
- },
- );
-
- it.each`
- actionName | event
- ${'add'} | ${'add-variable'}
- ${'update'} | ${'update-variable'}
- ${'delete'} | ${'delete-variable'}
- `(
- 'throws generic error when the mutation fails with no graphql errors and user performs $actionName variable',
- async ({ event }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
- throw new Error();
- });
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
- },
- );
- });
});
diff --git a/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js b/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
index c630278fbde..97051325f59 100644
--- a/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_project_variables_spec.js
@@ -1,215 +1,45 @@
-import Vue, { nextTick } from 'vue';
-import VueApollo from 'vue-apollo';
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import { createAlert } from '~/flash';
-import { resolvers } from '~/ci_variable_list/graphql/settings';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import ciProjectVariables from '~/ci_variable_list/components/ci_project_variables.vue';
-import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
-import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
-import getProjectEnvironments from '~/ci_variable_list/graphql/queries/project_environments.query.graphql';
-import getProjectVariables from '~/ci_variable_list/graphql/queries/project_variables.query.graphql';
+import ciVariableShared from '~/ci_variable_list/components/ci_variable_shared.vue';
-import addProjectVariable from '~/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql';
-import deleteProjectVariable from '~/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql';
-import updateProjectVariable from '~/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql';
-
-import {
- environmentFetchErrorText,
- genericMutationErrorText,
- variableFetchErrorText,
-} from '~/ci_variable_list/constants';
-
-import {
- devName,
- mockProjectEnvironments,
- mockProjectVariables,
- newVariable,
- prodName,
-} from '../mocks';
-
-jest.mock('~/flash');
-
-Vue.use(VueApollo);
+import { GRAPHQL_PROJECT_TYPE } from '~/ci_variable_list/constants';
const mockProvide = {
- endpoint: '/variables',
projectFullPath: '/namespace/project',
projectId: 1,
};
-describe('Ci Project Variable list', () => {
+describe('Ci Project Variable wrapper', () => {
let wrapper;
- let mockApollo;
- let mockEnvironments;
- let mockVariables;
-
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findCiTable = () => wrapper.findComponent(GlTable);
- const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
-
- // eslint-disable-next-line consistent-return
- const createComponentWithApollo = async ({ isLoading = false } = {}) => {
- const handlers = [
- [getProjectEnvironments, mockEnvironments],
- [getProjectVariables, mockVariables],
- ];
-
- mockApollo = createMockApollo(handlers, resolvers);
+ const findCiShared = () => wrapper.findComponent(ciVariableShared);
+ const createComponent = () => {
wrapper = shallowMount(ciProjectVariables, {
provide: mockProvide,
- apolloProvider: mockApollo,
- stubs: { ciVariableSettings, ciVariableTable },
});
-
- if (!isLoading) {
- return waitForPromises();
- }
};
beforeEach(() => {
- mockEnvironments = jest.fn();
- mockVariables = jest.fn();
+ createComponent();
});
afterEach(() => {
wrapper.destroy();
});
- describe('while queries are being fetch', () => {
- beforeEach(() => {
- createComponentWithApollo({ isLoading: true });
- });
-
- it('shows a loading icon', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- expect(findCiTable().exists()).toBe(false);
- });
- });
-
- describe('when queries are resolved', () => {
- describe('successfuly', () => {
- beforeEach(async () => {
- mockEnvironments.mockResolvedValue(mockProjectEnvironments);
- mockVariables.mockResolvedValue(mockProjectVariables);
-
- await createComponentWithApollo();
- });
-
- it('passes down the expected environments as props', () => {
- expect(findCiSettings().props('environments')).toEqual([prodName, devName]);
- });
-
- it('passes down the expected variables as props', () => {
- expect(findCiSettings().props('variables')).toEqual(
- mockProjectVariables.data.project.ciVariables.nodes,
- );
- });
-
- it('createAlert was not called', () => {
- expect(createAlert).not.toHaveBeenCalled();
- });
- });
-
- describe('with an error for variables', () => {
- beforeEach(async () => {
- mockEnvironments.mockResolvedValue(mockProjectEnvironments);
- mockVariables.mockRejectedValue();
-
- await createComponentWithApollo();
- });
-
- it('calls createAlert with the expected error message', () => {
- expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
- });
- });
-
- describe('with an error for environments', () => {
- beforeEach(async () => {
- mockEnvironments.mockRejectedValue();
- mockVariables.mockResolvedValue(mockProjectVariables);
-
- await createComponentWithApollo();
- });
-
- it('calls createAlert with the expected error message', () => {
- expect(createAlert).toHaveBeenCalledWith({ message: environmentFetchErrorText });
- });
- });
- });
-
- describe('mutations', () => {
- beforeEach(async () => {
- mockEnvironments.mockResolvedValue(mockProjectEnvironments);
- mockVariables.mockResolvedValue(mockProjectVariables);
-
- await createComponentWithApollo();
+ it('Passes down the correct props to ci_variable_shared', () => {
+ expect(findCiShared().props()).toEqual({
+ id: convertToGraphQLId(GRAPHQL_PROJECT_TYPE, mockProvide.projectId),
+ areScopedVariablesAvailable: true,
+ componentName: 'ProjectVariables',
+ fullPath: mockProvide.projectFullPath,
+ hideEnvironmentScope: false,
+ mutationData: wrapper.vm.$options.mutationData,
+ queryData: wrapper.vm.$options.queryData,
+ refetchAfterMutation: false,
});
- it.each`
- actionName | mutation | event
- ${'add'} | ${addProjectVariable} | ${'add-variable'}
- ${'update'} | ${updateProjectVariable} | ${'update-variable'}
- ${'delete'} | ${deleteProjectVariable} | ${'delete-variable'}
- `(
- 'calls the right mutation when user performs $actionName variable',
- async ({ event, mutation }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation,
- variables: {
- endpoint: mockProvide.endpoint,
- fullPath: mockProvide.projectFullPath,
- projectId: convertToGraphQLId('Project', mockProvide.projectId),
- variable: newVariable,
- },
- });
- },
- );
-
- it.each`
- actionName | event | mutationName
- ${'add'} | ${'add-variable'} | ${'addProjectVariable'}
- ${'update'} | ${'update-variable'} | ${'updateProjectVariable'}
- ${'delete'} | ${'delete-variable'} | ${'deleteProjectVariable'}
- `(
- 'throws with the specific graphql error if present when user performs $actionName variable',
- async ({ event, mutationName }) => {
- const graphQLErrorMessage = 'There is a problem with this graphQL action';
- jest
- .spyOn(wrapper.vm.$apollo, 'mutate')
- .mockResolvedValue({ data: { [mutationName]: { errors: [graphQLErrorMessage] } } });
- await findCiSettings().vm.$emit(event, newVariable);
- await nextTick();
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
- },
- );
-
- it.each`
- actionName | event
- ${'add'} | ${'add-variable'}
- ${'update'} | ${'update-variable'}
- ${'delete'} | ${'delete-variable'}
- `(
- 'throws generic error when the mutation fails with no graphql errors and user performs $actionName variable',
- async ({ event }) => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
- throw new Error();
- });
- await findCiSettings().vm.$emit(event, newVariable);
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
- expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
- },
- );
});
});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
index 1ea4e4f833b..e4771f040d1 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js
@@ -39,6 +39,7 @@ describe('Ci variable modal', () => {
const defaultProps = {
areScopedVariablesAvailable: true,
environments: [],
+ hideEnvironmentScope: false,
mode: ADD_VARIABLE_ACTION,
selectedVariable: {},
variable: [],
@@ -75,6 +76,7 @@ describe('Ci variable modal', () => {
const findEnvScopeInput = () =>
wrapper.findByTestId('environment-scope').findComponent(GlFormInput);
const findVariableTypeDropdown = () => wrapper.find('#ci-variable-type');
+ const findEnvironmentScopeText = () => wrapper.findByText('Environment scope');
afterEach(() => {
wrapper.destroy();
@@ -250,39 +252,83 @@ describe('Ci variable modal', () => {
describe('Environment scope', () => {
describe('when feature is available', () => {
- it('renders the environment dropdown', () => {
- createComponent({
- mountFn: mountExtended,
- props: {
- areScopedVariablesAvailable: true,
- },
+ describe('and section is not hidden', () => {
+ beforeEach(() => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: true,
+ hideEnvironmentScope: false,
+ },
+ });
});
- expect(findCiEnvironmentsDropdown().exists()).toBe(true);
- expect(findCiEnvironmentsDropdown().isVisible()).toBe(true);
- });
+ it('renders the environment dropdown and section title', () => {
+ expect(findCiEnvironmentsDropdown().exists()).toBe(true);
+ expect(findCiEnvironmentsDropdown().isVisible()).toBe(true);
+ expect(findEnvironmentScopeText().exists()).toBe(true);
+ });
- it('renders a link to documentation on scopes', () => {
- createComponent({ mountFn: mountExtended });
+ it('renders a link to documentation on scopes', () => {
+ const link = findEnvScopeLink();
+
+ expect(link.attributes('title')).toBe(ENVIRONMENT_SCOPE_LINK_TITLE);
+ expect(link.attributes('href')).toBe(defaultProvide.environmentScopeLink);
+ });
+ });
- const link = findEnvScopeLink();
+ describe('and section is hidden', () => {
+ beforeEach(() => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: true,
+ hideEnvironmentScope: true,
+ },
+ });
+ });
- expect(link.attributes('title')).toBe(ENVIRONMENT_SCOPE_LINK_TITLE);
- expect(link.attributes('href')).toBe(defaultProvide.environmentScopeLink);
+ it('does not renders the environment dropdown and section title', () => {
+ expect(findCiEnvironmentsDropdown().exists()).toBe(false);
+ expect(findEnvironmentScopeText().exists()).toBe(false);
+ });
});
});
describe('when feature is not available', () => {
- it('disables the dropdown', () => {
- createComponent({
- mountFn: mountExtended,
- props: {
- areScopedVariablesAvailable: false,
- },
+ describe('and section is not hidden', () => {
+ beforeEach(() => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: false,
+ hideEnvironmentScope: false,
+ },
+ });
});
- expect(findCiEnvironmentsDropdown().exists()).toBe(false);
- expect(findEnvScopeInput().attributes('readonly')).toBe('readonly');
+ it('disables the dropdown', () => {
+ expect(findCiEnvironmentsDropdown().exists()).toBe(false);
+ expect(findEnvironmentScopeText().exists()).toBe(true);
+ expect(findEnvScopeInput().attributes('readonly')).toBe('readonly');
+ });
+ });
+
+ describe('and section is hidden', () => {
+ beforeEach(() => {
+ createComponent({
+ mountFn: mountExtended,
+ props: {
+ areScopedVariablesAvailable: false,
+ hideEnvironmentScope: true,
+ },
+ });
+ });
+
+ it('hides the dropdown', () => {
+ expect(findEnvironmentScopeText().exists()).toBe(false);
+ expect(findCiEnvironmentsDropdown().exists()).toBe(false);
+ });
});
});
});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js
deleted file mode 100644
index 4d0c378d10e..00000000000
--- a/spec/frontend/ci_variable_list/components/ci_variable_popover_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import CiVariablePopover from '~/ci_variable_list/components/ci_variable_popover.vue';
-import mockData from '../services/mock_data';
-
-describe('Ci Variable Popover', () => {
- let wrapper;
-
- const defaultProps = {
- target: 'ci-variable-value-22',
- value: mockData.mockPemCert,
- tooltipText: 'Copy value',
- };
-
- const createComponent = (props = defaultProps) => {
- wrapper = shallowMount(CiVariablePopover, {
- propsData: { ...props },
- });
- };
-
- const findButton = () => wrapper.findComponent(GlButton);
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('displays max count plus ... when character count is over 95', () => {
- expect(wrapper.text()).toHaveLength(98);
- });
-
- it('copies full value to clipboard', () => {
- expect(findButton().attributes('data-clipboard-text')).toEqual(mockData.mockPemCert);
- });
-
- it('displays full value when count is less than max count', () => {
- createComponent({
- target: 'ci-variable-value-22',
- value: 'test_variable_value',
- tooltipText: 'Copy value',
- });
- expect(wrapper.text()).toEqual('test_variable_value');
- });
-});
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
index 5c77ce71b41..8b5a0f7ae9d 100644
--- a/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
+++ b/spec/frontend/ci_variable_list/components/ci_variable_settings_spec.js
@@ -18,6 +18,7 @@ describe('Ci variable table', () => {
const defaultProps = {
areScopedVariablesAvailable: true,
environments: mapEnvironmentNames(mockEnvs),
+ hideEnvironmentScope: false,
isLoading: false,
variables: mockVariablesWithScopes(projectString),
};
@@ -56,6 +57,7 @@ describe('Ci variable table', () => {
expect(findCiVariableModal().props()).toEqual({
areScopedVariablesAvailable: defaultProps.areScopedVariablesAvailable,
environments: defaultProps.environments,
+ hideEnvironmentScope: defaultProps.hideEnvironmentScope,
variables: defaultProps.variables,
mode: ADD_VARIABLE_ACTION,
selectedVariable: {},
diff --git a/spec/frontend/ci_variable_list/components/ci_variable_shared_spec.js b/spec/frontend/ci_variable_list/components/ci_variable_shared_spec.js
new file mode 100644
index 00000000000..0cc0ee7a9c7
--- /dev/null
+++ b/spec/frontend/ci_variable_list/components/ci_variable_shared_spec.js
@@ -0,0 +1,428 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { createAlert } from '~/flash';
+import { resolvers } from '~/ci_variable_list/graphql/settings';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+
+import ciVariableShared from '~/ci_variable_list/components/ci_variable_shared.vue';
+import ciVariableSettings from '~/ci_variable_list/components/ci_variable_settings.vue';
+import ciVariableTable from '~/ci_variable_list/components/ci_variable_table.vue';
+import getProjectEnvironments from '~/ci_variable_list/graphql/queries/project_environments.query.graphql';
+import getAdminVariables from '~/ci_variable_list/graphql/queries/variables.query.graphql';
+import getGroupVariables from '~/ci_variable_list/graphql/queries/group_variables.query.graphql';
+import getProjectVariables from '~/ci_variable_list/graphql/queries/project_variables.query.graphql';
+
+import {
+ ADD_MUTATION_ACTION,
+ DELETE_MUTATION_ACTION,
+ UPDATE_MUTATION_ACTION,
+ environmentFetchErrorText,
+ genericMutationErrorText,
+ variableFetchErrorText,
+} from '~/ci_variable_list/constants';
+
+import {
+ createGroupProps,
+ createInstanceProps,
+ createProjectProps,
+ devName,
+ mockProjectEnvironments,
+ mockProjectVariables,
+ newVariable,
+ prodName,
+ mockGroupVariables,
+ mockAdminVariables,
+} from '../mocks';
+
+jest.mock('~/flash');
+
+Vue.use(VueApollo);
+
+const mockProvide = {
+ endpoint: '/variables',
+};
+
+const defaultProps = {
+ areScopedVariablesAvailable: true,
+ hideEnvironmentScope: false,
+ refetchAfterMutation: false,
+};
+
+describe('Ci Variable Shared Component', () => {
+ let wrapper;
+
+ let mockApollo;
+ let mockEnvironments;
+ let mockVariables;
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findCiTable = () => wrapper.findComponent(GlTable);
+ const findCiSettings = () => wrapper.findComponent(ciVariableSettings);
+
+ // eslint-disable-next-line consistent-return
+ async function createComponentWithApollo({
+ customHandlers = null,
+ isLoading = false,
+ props = { ...createProjectProps() },
+ } = {}) {
+ const handlers = customHandlers || [
+ [getProjectEnvironments, mockEnvironments],
+ [getProjectVariables, mockVariables],
+ ];
+
+ mockApollo = createMockApollo(handlers, resolvers);
+
+ wrapper = shallowMount(ciVariableShared, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ provide: mockProvide,
+ apolloProvider: mockApollo,
+ stubs: { ciVariableSettings, ciVariableTable },
+ });
+
+ if (!isLoading) {
+ return waitForPromises();
+ }
+ }
+
+ beforeEach(() => {
+ mockEnvironments = jest.fn();
+ mockVariables = jest.fn();
+ });
+
+ describe('while queries are being fetch', () => {
+ beforeEach(() => {
+ createComponentWithApollo({ isLoading: true });
+ });
+
+ it('shows a loading icon', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(findCiTable().exists()).toBe(false);
+ });
+ });
+
+ describe('when queries are resolved', () => {
+ describe('successfuly', () => {
+ beforeEach(async () => {
+ mockEnvironments.mockResolvedValue(mockProjectEnvironments);
+ mockVariables.mockResolvedValue(mockProjectVariables);
+
+ await createComponentWithApollo();
+ });
+
+ it('passes down the expected environments as props', () => {
+ expect(findCiSettings().props('environments')).toEqual([prodName, devName]);
+ });
+
+ it('passes down the expected variables as props', () => {
+ expect(findCiSettings().props('variables')).toEqual(
+ mockProjectVariables.data.project.ciVariables.nodes,
+ );
+ });
+
+ it('createAlert was not called', () => {
+ expect(createAlert).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('with an error for variables', () => {
+ beforeEach(async () => {
+ mockEnvironments.mockResolvedValue(mockProjectEnvironments);
+ mockVariables.mockRejectedValue();
+
+ await createComponentWithApollo();
+ });
+
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: variableFetchErrorText });
+ });
+ });
+
+ describe('with an error for environments', () => {
+ beforeEach(async () => {
+ mockEnvironments.mockRejectedValue();
+ mockVariables.mockResolvedValue(mockProjectVariables);
+
+ await createComponentWithApollo();
+ });
+
+ it('calls createAlert with the expected error message', () => {
+ expect(createAlert).toHaveBeenCalledWith({ message: environmentFetchErrorText });
+ });
+ });
+ });
+
+ describe('environment query', () => {
+ describe('when there is an environment key in queryData', () => {
+ beforeEach(async () => {
+ mockEnvironments.mockResolvedValue(mockProjectEnvironments);
+ mockVariables.mockResolvedValue(mockProjectVariables);
+
+ await createComponentWithApollo({ props: { ...createProjectProps() } });
+ });
+
+ it('is executed', () => {
+ expect(mockVariables).toHaveBeenCalled();
+ });
+ });
+
+ describe('when there isnt an environment key in queryData', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+
+ await createComponentWithApollo({ props: { ...createGroupProps() } });
+ });
+
+ it('is skipped', () => {
+ expect(mockVariables).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('mutations', () => {
+ const groupProps = createGroupProps();
+
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+
+ await createComponentWithApollo({
+ customHandlers: [[getGroupVariables, mockVariables]],
+ props: groupProps,
+ });
+ });
+ it.each`
+ actionName | mutation | event
+ ${'add'} | ${groupProps.mutationData[ADD_MUTATION_ACTION]} | ${'add-variable'}
+ ${'update'} | ${groupProps.mutationData[UPDATE_MUTATION_ACTION]} | ${'update-variable'}
+ ${'delete'} | ${groupProps.mutationData[DELETE_MUTATION_ACTION]} | ${'delete-variable'}
+ `(
+ 'calls the right mutation from propsData when user performs $actionName variable',
+ async ({ event, mutation }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
+
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation,
+ variables: {
+ endpoint: mockProvide.endpoint,
+ fullPath: groupProps.fullPath,
+ id: convertToGraphQLId('Group', groupProps.id),
+ variable: newVariable,
+ },
+ });
+ },
+ );
+
+ it.each`
+ actionName | event
+ ${'add'} | ${'add-variable'}
+ ${'update'} | ${'update-variable'}
+ ${'delete'} | ${'delete-variable'}
+ `(
+ 'throws with the specific graphql error if present when user performs $actionName variable',
+ async ({ event }) => {
+ const graphQLErrorMessage = 'There is a problem with this graphQL action';
+ jest
+ .spyOn(wrapper.vm.$apollo, 'mutate')
+ .mockResolvedValue({ data: { ciVariableMutation: { errors: [graphQLErrorMessage] } } });
+ await findCiSettings().vm.$emit(event, newVariable);
+ await nextTick();
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalledWith({ message: graphQLErrorMessage });
+ },
+ );
+
+ it.each`
+ actionName | event
+ ${'add'} | ${'add-variable'}
+ ${'update'} | ${'update-variable'}
+ ${'delete'} | ${'delete-variable'}
+ `(
+ 'throws generic error on failure with no graphql errors and user performs $actionName variable',
+ async ({ event }) => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockImplementationOnce(() => {
+ throw new Error();
+ });
+ await findCiSettings().vm.$emit(event, newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalled();
+ expect(createAlert).toHaveBeenCalledWith({ message: genericMutationErrorText });
+ },
+ );
+
+ describe('without fullpath and ID props', () => {
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockAdminVariables);
+
+ await createComponentWithApollo({
+ customHandlers: [[getAdminVariables, mockVariables]],
+ props: createInstanceProps(),
+ });
+ });
+
+ it('does not pass fullPath and ID to the mutation', async () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue();
+
+ await findCiSettings().vm.$emit('add-variable', newVariable);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: wrapper.props().mutationData[ADD_MUTATION_ACTION],
+ variables: {
+ endpoint: mockProvide.endpoint,
+ variable: newVariable,
+ },
+ });
+ });
+ });
+ });
+
+ describe('Props', () => {
+ describe('in a specific context as', () => {
+ it.each`
+ name | mockVariablesValue | mockEnvironmentsValue | withEnvironments | expectedEnvironments | propsFn | mutation
+ ${'project'} | ${mockProjectVariables} | ${mockProjectEnvironments} | ${true} | ${['prod', 'dev']} | ${createProjectProps} | ${null}
+ ${'group'} | ${mockGroupVariables} | ${[]} | ${false} | ${[]} | ${createGroupProps} | ${getGroupVariables}
+ ${'instance'} | ${mockAdminVariables} | ${[]} | ${false} | ${[]} | ${createInstanceProps} | ${getAdminVariables}
+ `(
+ 'passes down all the required props when its a $name component',
+ async ({
+ mutation,
+ mockVariablesValue,
+ mockEnvironmentsValue,
+ withEnvironments,
+ expectedEnvironments,
+ propsFn,
+ }) => {
+ const props = propsFn();
+
+ mockVariables.mockResolvedValue(mockVariablesValue);
+
+ if (withEnvironments) {
+ mockEnvironments.mockResolvedValue(mockEnvironmentsValue);
+ }
+
+ let customHandlers = null;
+
+ if (mutation) {
+ customHandlers = [[mutation, mockVariables]];
+ }
+
+ await createComponentWithApollo({ customHandlers, props });
+
+ expect(findCiSettings().props()).toEqual({
+ areScopedVariablesAvailable: wrapper.props().areScopedVariablesAvailable,
+ hideEnvironmentScope: defaultProps.hideEnvironmentScope,
+ isLoading: false,
+ variables: wrapper.props().queryData.ciVariables.lookup(mockVariablesValue.data)?.nodes,
+ environments: expectedEnvironments,
+ });
+ },
+ );
+ });
+
+ describe('refetchAfterMutation', () => {
+ it.each`
+ bool | text
+ ${true} | ${'refetches the variables'}
+ ${false} | ${'does not refetch the variables'}
+ `('when $bool it $text', async ({ bool }) => {
+ await createComponentWithApollo({
+ props: { ...createInstanceProps(), refetchAfterMutation: bool },
+ });
+
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({ data: {} });
+ jest.spyOn(wrapper.vm.$apollo.queries.ciVariables, 'refetch').mockImplementation(jest.fn());
+
+ await findCiSettings().vm.$emit('add-variable', newVariable);
+
+ await nextTick();
+
+ if (bool) {
+ expect(wrapper.vm.$apollo.queries.ciVariables.refetch).toHaveBeenCalled();
+ } else {
+ expect(wrapper.vm.$apollo.queries.ciVariables.refetch).not.toHaveBeenCalled();
+ }
+ });
+ });
+
+ describe('Validators', () => {
+ describe('queryData', () => {
+ let error;
+
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+ });
+
+ it('will mount component with right data', async () => {
+ try {
+ await createComponentWithApollo({
+ customHandlers: [[getGroupVariables, mockVariables]],
+ props: { ...createGroupProps() },
+ });
+ } catch (e) {
+ error = e;
+ } finally {
+ expect(wrapper.exists()).toBe(true);
+ expect(error).toBeUndefined();
+ }
+ });
+
+ it('will not mount component with wrong data', async () => {
+ try {
+ await createComponentWithApollo({
+ customHandlers: [[getGroupVariables, mockVariables]],
+ props: { ...createGroupProps(), queryData: { wrongKey: {} } },
+ });
+ } catch (e) {
+ error = e;
+ } finally {
+ expect(wrapper.exists()).toBe(false);
+ expect(error.toString()).toContain('custom validator check failed for prop');
+ }
+ });
+ });
+
+ describe('mutationData', () => {
+ let error;
+
+ beforeEach(async () => {
+ mockVariables.mockResolvedValue(mockGroupVariables);
+ });
+
+ it('will mount component with right data', async () => {
+ try {
+ await createComponentWithApollo({
+ props: { ...createGroupProps() },
+ });
+ } catch (e) {
+ error = e;
+ } finally {
+ expect(wrapper.exists()).toBe(true);
+ expect(error).toBeUndefined();
+ }
+ });
+
+ it('will not mount component with wrong data', async () => {
+ try {
+ await createComponentWithApollo({
+ props: { ...createGroupProps(), mutationData: { wrongKey: {} } },
+ });
+ } catch (e) {
+ error = e;
+ } finally {
+ expect(wrapper.exists()).toBe(false);
+ expect(error.toString()).toContain('custom validator check failed for prop');
+ }
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_environments_dropdown_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_environments_dropdown_spec.js
deleted file mode 100644
index b3e23ba4201..00000000000
--- a/spec/frontend/ci_variable_list/components/legacy_ci_environments_dropdown_spec.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import { GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
-import Vuex from 'vuex';
-import LegacyCiEnvironmentsDropdown from '~/ci_variable_list/components/legacy_ci_environments_dropdown.vue';
-
-Vue.use(Vuex);
-
-describe('Ci environments dropdown', () => {
- let wrapper;
- let store;
-
- const enterSearchTerm = (value) =>
- wrapper.find('[data-testid="ci-environment-search"]').setValue(value);
-
- const createComponent = (term) => {
- store = new Vuex.Store({
- getters: {
- joinedEnvironments: () => ['dev', 'prod', 'staging'],
- },
- });
-
- wrapper = mount(LegacyCiEnvironmentsDropdown, {
- store,
- propsData: {
- value: term,
- },
- });
- enterSearchTerm(term);
- };
-
- const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
- const findDropdownItemByIndex = (index) => wrapper.findAllComponents(GlDropdownItem).at(index);
- const findActiveIconByIndex = (index) => findDropdownItemByIndex(index).findComponent(GlIcon);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('No environments found', () => {
- beforeEach(() => {
- createComponent('stable');
- });
-
- it('renders create button with search term if environments do not contain search term', () => {
- expect(findAllDropdownItems()).toHaveLength(2);
- expect(findDropdownItemByIndex(1).text()).toBe('Create wildcard: stable');
- });
-
- it('renders empty results message', () => {
- expect(findDropdownItemByIndex(0).text()).toBe('No matching results');
- });
- });
-
- describe('Search term is empty', () => {
- beforeEach(() => {
- createComponent('');
- });
-
- it('renders all environments when search term is empty', () => {
- expect(findAllDropdownItems()).toHaveLength(3);
- expect(findDropdownItemByIndex(0).text()).toBe('dev');
- expect(findDropdownItemByIndex(1).text()).toBe('prod');
- expect(findDropdownItemByIndex(2).text()).toBe('staging');
- });
-
- it('should not display active checkmark on the inactive stage', () => {
- expect(findActiveIconByIndex(0).classes('gl-visibility-hidden')).toBe(true);
- });
- });
-
- describe('Environments found', () => {
- beforeEach(async () => {
- createComponent('prod');
- await nextTick();
- });
-
- it('renders only the environment searched for', () => {
- expect(findAllDropdownItems()).toHaveLength(1);
- expect(findDropdownItemByIndex(0).text()).toBe('prod');
- });
-
- it('should not display create button', () => {
- const environments = findAllDropdownItems().filter((env) => env.text().startsWith('Create'));
- expect(environments).toHaveLength(0);
- expect(findAllDropdownItems()).toHaveLength(1);
- });
-
- it('should not display empty results message', () => {
- expect(wrapper.findComponent({ ref: 'noMatchingResults' }).exists()).toBe(false);
- });
-
- it('should display active checkmark if active', () => {
- expect(findActiveIconByIndex(0).classes('gl-visibility-hidden')).toBe(false);
- });
-
- it('should clear the search term when showing the dropdown', () => {
- wrapper.findComponent(GlDropdown).trigger('click');
-
- expect(wrapper.find('[data-testid="ci-environment-search"]').text()).toBe('');
- });
-
- describe('Custom events', () => {
- it('should emit selectEnvironment if an environment is clicked', () => {
- findDropdownItemByIndex(0).vm.$emit('click');
- expect(wrapper.emitted('selectEnvironment')).toEqual([['prod']]);
- });
-
- it('should emit createClicked if an environment is clicked', async () => {
- createComponent('newscope');
-
- await nextTick();
- findDropdownItemByIndex(1).vm.$emit('click');
- expect(wrapper.emitted('createClicked')).toEqual([['newscope']]);
- });
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js
deleted file mode 100644
index b607232907b..00000000000
--- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_modal_spec.js
+++ /dev/null
@@ -1,323 +0,0 @@
-import { GlButton, GlFormInput } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { mockTracking } from 'helpers/tracking_helper';
-import CiEnvironmentsDropdown from '~/ci_variable_list/components/ci_environments_dropdown.vue';
-import LegacyCiVariableModal from '~/ci_variable_list/components/legacy_ci_variable_modal.vue';
-import {
- AWS_ACCESS_KEY_ID,
- EVENT_LABEL,
- EVENT_ACTION,
- ENVIRONMENT_SCOPE_LINK_TITLE,
-} from '~/ci_variable_list/constants';
-import createStore from '~/ci_variable_list/store';
-import mockData from '../services/mock_data';
-import ModalStub from '../stubs';
-
-Vue.use(Vuex);
-
-describe('Ci variable modal', () => {
- let wrapper;
- let store;
- let trackingSpy;
-
- const maskableRegex = '^[a-zA-Z0-9_+=/@:.~-]{8,}$';
-
- const createComponent = (method, options = {}) => {
- store = createStore({
- maskableRegex,
- isGroup: options.isGroup,
- environmentScopeLink: '/help/environments',
- });
- wrapper = method(LegacyCiVariableModal, {
- attachTo: document.body,
- stubs: {
- GlModal: ModalStub,
- },
- store,
- ...options,
- });
- };
-
- const findCiEnvironmentsDropdown = () => wrapper.findComponent(CiEnvironmentsDropdown);
- const findModal = () => wrapper.findComponent(ModalStub);
- const findAddorUpdateButton = () => findModal().find('[data-testid="ciUpdateOrAddVariableBtn"]');
- const deleteVariableButton = () =>
- findModal()
- .findAllComponents(GlButton)
- .wrappers.find((button) => button.props('variant') === 'danger');
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('Basic interactions', () => {
- beforeEach(() => {
- createComponent(shallowMount);
- });
-
- it('button is disabled when no key/value pair are present', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBe('true');
- });
- });
-
- 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(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
- });
-
- it('Add variable button dispatches addVariable action', () => {
- findAddorUpdateButton().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.each`
- value | secret | rendered
- ${'value'} | ${'secret_value'} | ${false}
- ${'dollar$ign'} | ${'dollar$ign'} | ${true}
- `('Adding a new variable', ({ value, secret, rendered }) => {
- beforeEach(() => {
- const [variable] = mockData.mockVariables;
- const invalidKeyVariable = {
- ...variable,
- key: 'key',
- value,
- secret_value: secret,
- };
- createComponent(mount);
- store.state.variable = invalidKeyVariable;
- trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- });
-
- it(`${rendered ? 'renders' : 'does not render'} the variable reference warning`, () => {
- const warning = wrapper.find(`[data-testid='contains-variable-reference']`);
- expect(warning.exists()).toBe(rendered);
- });
- });
-
- 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(findAddorUpdateButton().text()).toBe('Update variable');
- });
-
- it('Update variable button dispatches updateVariable with correct variable', () => {
- findAddorUpdateButton().vm.$emit('click');
- expect(store.dispatch).toHaveBeenCalledWith('updateVariable');
- });
-
- 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');
- });
- });
-
- describe('Environment scope', () => {
- describe('group level variables', () => {
- it('renders the environment dropdown', () => {
- createComponent(shallowMount, {
- isGroup: true,
- provide: {
- glFeatures: {
- groupScopedCiVariables: true,
- },
- },
- });
-
- expect(findCiEnvironmentsDropdown().exists()).toBe(true);
- expect(findCiEnvironmentsDropdown().isVisible()).toBe(true);
- });
-
- describe('licensed feature is not available', () => {
- it('disables the dropdown', () => {
- createComponent(mount, {
- isGroup: true,
- provide: {
- glFeatures: {
- groupScopedCiVariables: false,
- },
- },
- });
-
- const environmentScopeInput = wrapper
- .find('[data-testid="environment-scope"]')
- .findComponent(GlFormInput);
- expect(findCiEnvironmentsDropdown().exists()).toBe(false);
- expect(environmentScopeInput.attributes('readonly')).toBe('readonly');
- });
- });
- });
-
- it('renders a link to documentation on scopes', () => {
- createComponent(mount);
-
- const link = wrapper.find('[data-testid="environment-scope-link"]');
-
- expect(link.attributes('title')).toBe(ENVIRONMENT_SCOPE_LINK_TITLE);
- expect(link.attributes('href')).toBe('/help/environments');
- });
- });
-
- describe('Validations', () => {
- const maskError = 'This variable can not be masked.';
-
- 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;
- trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- });
-
- it('disables the submit button', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBe('disabled');
- });
-
- it('shows the correct error text', () => {
- expect(findModal().text()).toContain(maskError);
- });
-
- it('sends the correct tracking event', () => {
- expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
- label: EVENT_LABEL,
- property: ';',
- });
- });
- });
-
- describe.each`
- value | secret | masked | eventSent | trackingErrorProperty
- ${'value'} | ${'secretValue'} | ${false} | ${0} | ${null}
- ${'shortMasked'} | ${'short'} | ${true} | ${0} | ${null}
- ${'withDollar$Sign'} | ${'dollar$ign'} | ${false} | ${1} | ${'$'}
- ${'withDollar$Sign'} | ${'dollar$ign'} | ${true} | ${1} | ${'$'}
- ${'unsupported'} | ${'unsupported|char'} | ${true} | ${1} | ${'|'}
- ${'unsupportedMasked'} | ${'unsupported|char'} | ${false} | ${0} | ${null}
- `('Adding a new variable', ({ value, secret, masked, eventSent, trackingErrorProperty }) => {
- beforeEach(() => {
- const [variable] = mockData.mockVariables;
- const invalidKeyVariable = {
- ...variable,
- key: 'key',
- value,
- secret_value: secret,
- masked,
- };
- createComponent(mount);
- store.state.variable = invalidKeyVariable;
- trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
- });
-
- it(`${
- eventSent > 0 ? 'sends the correct' : 'does not send the'
- } variable validation tracking event`, () => {
- expect(trackingSpy).toHaveBeenCalledTimes(eventSent);
-
- if (eventSent > 0) {
- expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
- label: EVENT_LABEL,
- property: trackingErrorProperty,
- });
- }
- });
- });
-
- describe('when both states are valid', () => {
- beforeEach(() => {
- const [variable] = mockData.mockVariables;
- const validMaskandKeyVariable = {
- ...variable,
- key: AWS_ACCESS_KEY_ID,
- value: '12345678',
- secret_value: '87654321',
- masked: true,
- };
- createComponent(mount);
- store.state.variable = validMaskandKeyVariable;
- });
-
- it('does not disable the submit button', () => {
- expect(findAddorUpdateButton().attributes('disabled')).toBeUndefined();
- });
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js
deleted file mode 100644
index 7def4dd4f29..00000000000
--- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_settings_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
-import LegacyCiVariableSettings from '~/ci_variable_list/components/legacy_ci_variable_settings.vue';
-import createStore from '~/ci_variable_list/store';
-
-Vue.use(Vuex);
-
-describe('Ci variable table', () => {
- let wrapper;
- let store;
- let isProject;
-
- const createComponent = (projectState) => {
- store = createStore();
- store.state.isProject = projectState;
- jest.spyOn(store, 'dispatch').mockImplementation();
- wrapper = shallowMount(LegacyCiVariableSettings, {
- store,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('dispatches fetchEnvironments when mounted', () => {
- isProject = true;
- createComponent(isProject);
- expect(store.dispatch).toHaveBeenCalledWith('fetchEnvironments');
- });
-
- it('does not dispatch fetchenvironments when in group context', () => {
- isProject = false;
- createComponent(isProject);
- expect(store.dispatch).not.toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend/ci_variable_list/components/legacy_ci_variable_table_spec.js b/spec/frontend/ci_variable_list/components/legacy_ci_variable_table_spec.js
deleted file mode 100644
index 310afc8003a..00000000000
--- a/spec/frontend/ci_variable_list/components/legacy_ci_variable_table_spec.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import LegacyCiVariableTable from '~/ci_variable_list/components/legacy_ci_variable_table.vue';
-import createStore from '~/ci_variable_list/store';
-import mockData from '../services/mock_data';
-
-Vue.use(Vuex);
-
-describe('Ci variable table', () => {
- let wrapper;
- let store;
-
- const createComponent = () => {
- store = createStore();
- jest.spyOn(store, 'dispatch').mockImplementation();
- wrapper = mountExtended(LegacyCiVariableTable, {
- attachTo: document.body,
- store,
- });
- };
-
- const findRevealButton = () => wrapper.findByText('Reveal values');
- const findEditButton = () => wrapper.findByLabelText('Edit');
- const findEmptyVariablesPlaceholder = () => wrapper.findByText('There are no variables yet.');
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('dispatches fetchVariables when mounted', () => {
- expect(store.dispatch).toHaveBeenCalledWith('fetchVariables');
- });
-
- describe('When table is empty', () => {
- beforeEach(() => {
- store.state.variables = [];
- });
-
- it('displays empty message', () => {
- expect(findEmptyVariablesPlaceholder().exists()).toBe(true);
- });
-
- it('hides the reveal button', () => {
- expect(findRevealButton().exists()).toBe(false);
- });
- });
-
- describe('When table has variables', () => {
- beforeEach(() => {
- store.state.variables = mockData.mockVariables;
- });
-
- it('does not display the empty message', () => {
- expect(findEmptyVariablesPlaceholder().exists()).toBe(false);
- });
-
- it('displays the reveal button', () => {
- expect(findRevealButton().exists()).toBe(true);
- });
-
- it('displays the correct amount of variables', async () => {
- expect(wrapper.findAll('.js-ci-variable-row')).toHaveLength(1);
- });
- });
-
- describe('Table click actions', () => {
- beforeEach(() => {
- store.state.variables = mockData.mockVariables;
- });
-
- it('reveals secret values when button is clicked', () => {
- findRevealButton().trigger('click');
- expect(store.dispatch).toHaveBeenCalledWith('toggleValues', false);
- });
-
- it('dispatches editVariable with correct variable to edit', () => {
- findEditButton().trigger('click');
- expect(store.dispatch).toHaveBeenCalledWith('editVariable', mockData.mockVariables[0]);
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/mocks.js b/spec/frontend/ci_variable_list/mocks.js
index 6f3e73f8b83..03b77f80430 100644
--- a/spec/frontend/ci_variable_list/mocks.js
+++ b/spec/frontend/ci_variable_list/mocks.js
@@ -1,10 +1,28 @@
import {
+ ADD_MUTATION_ACTION,
+ DELETE_MUTATION_ACTION,
+ UPDATE_MUTATION_ACTION,
variableTypes,
groupString,
instanceString,
projectString,
} from '~/ci_variable_list/constants';
+import addAdminVariable from '~/ci_variable_list/graphql/mutations/admin_add_variable.mutation.graphql';
+import deleteAdminVariable from '~/ci_variable_list/graphql/mutations/admin_delete_variable.mutation.graphql';
+import updateAdminVariable from '~/ci_variable_list/graphql/mutations/admin_update_variable.mutation.graphql';
+import addGroupVariable from '~/ci_variable_list/graphql/mutations/group_add_variable.mutation.graphql';
+import deleteGroupVariable from '~/ci_variable_list/graphql/mutations/group_delete_variable.mutation.graphql';
+import updateGroupVariable from '~/ci_variable_list/graphql/mutations/group_update_variable.mutation.graphql';
+import addProjectVariable from '~/ci_variable_list/graphql/mutations/project_add_variable.mutation.graphql';
+import deleteProjectVariable from '~/ci_variable_list/graphql/mutations/project_delete_variable.mutation.graphql';
+import updateProjectVariable from '~/ci_variable_list/graphql/mutations/project_update_variable.mutation.graphql';
+
+import getAdminVariables from '~/ci_variable_list/graphql/queries/variables.query.graphql';
+import getGroupVariables from '~/ci_variable_list/graphql/queries/group_variables.query.graphql';
+import getProjectEnvironments from '~/ci_variable_list/graphql/queries/project_environments.query.graphql';
+import getProjectVariables from '~/ci_variable_list/graphql/queries/project_variables.query.graphql';
+
export const devName = 'dev';
export const prodName = 'prod';
@@ -118,3 +136,62 @@ export const newVariable = {
value: 'devops',
variableType: variableTypes.variableType,
};
+
+export const createProjectProps = () => {
+ return {
+ componentName: 'ProjectVariable',
+ fullPath: '/namespace/project/',
+ id: 'gid://gitlab/Project/20',
+ mutationData: {
+ [ADD_MUTATION_ACTION]: addProjectVariable,
+ [UPDATE_MUTATION_ACTION]: updateProjectVariable,
+ [DELETE_MUTATION_ACTION]: deleteProjectVariable,
+ },
+ queryData: {
+ ciVariables: {
+ lookup: (data) => data?.project?.ciVariables,
+ query: getProjectVariables,
+ },
+ environments: {
+ lookup: (data) => data?.project?.environments,
+ query: getProjectEnvironments,
+ },
+ },
+ };
+};
+
+export const createGroupProps = () => {
+ return {
+ componentName: 'GroupVariable',
+ fullPath: '/my-group',
+ id: 'gid://gitlab/Group/20',
+ mutationData: {
+ [ADD_MUTATION_ACTION]: addGroupVariable,
+ [UPDATE_MUTATION_ACTION]: updateGroupVariable,
+ [DELETE_MUTATION_ACTION]: deleteGroupVariable,
+ },
+ queryData: {
+ ciVariables: {
+ lookup: (data) => data?.group?.ciVariables,
+ query: getGroupVariables,
+ },
+ },
+ };
+};
+
+export const createInstanceProps = () => {
+ return {
+ componentName: 'InstanceVariable',
+ mutationData: {
+ [ADD_MUTATION_ACTION]: addAdminVariable,
+ [UPDATE_MUTATION_ACTION]: updateAdminVariable,
+ [DELETE_MUTATION_ACTION]: deleteAdminVariable,
+ },
+ queryData: {
+ ciVariables: {
+ lookup: (data) => data?.ciVariables,
+ query: getAdminVariables,
+ },
+ },
+ };
+};
diff --git a/spec/frontend/ci_variable_list/store/actions_spec.js b/spec/frontend/ci_variable_list/store/actions_spec.js
deleted file mode 100644
index e8c81a53a55..00000000000
--- a/spec/frontend/ci_variable_list/store/actions_spec.js
+++ /dev/null
@@ -1,319 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import Api from '~/api';
-import * as actions from '~/ci_variable_list/store/actions';
-import * as types from '~/ci_variable_list/store/mutation_types';
-import getInitialState from '~/ci_variable_list/store/state';
-import { prepareDataForDisplay, prepareEnvironments } from '~/ci_variable_list/store/utils';
-import { createAlert } from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import mockData from '../services/mock_data';
-
-jest.mock('~/api.js');
-jest.mock('~/flash.js');
-
-describe('CI variable list store actions', () => {
- let mock;
- let state;
- const mockVariable = {
- environment_scope: '*',
- id: 63,
- key: 'test_var',
- masked: false,
- protected: false,
- value: 'test_val',
- variable_type: 'env_var',
- _destory: true,
- };
- const payloadError = new Error('Request failed with status code 500');
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- state = getInitialState();
- state.endpoint = '/variables';
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('toggleValues', () => {
- const valuesHidden = false;
- it('commits TOGGLE_VALUES mutation', () => {
- testAction(actions.toggleValues, valuesHidden, {}, [
- {
- type: types.TOGGLE_VALUES,
- payload: valuesHidden,
- },
- ]);
- });
- });
-
- describe('clearModal', () => {
- it('commits CLEAR_MODAL mutation', () => {
- testAction(actions.clearModal, {}, {}, [
- {
- type: types.CLEAR_MODAL,
- },
- ]);
- });
- });
-
- describe('resetEditing', () => {
- it('commits RESET_EDITING mutation', () => {
- testAction(
- actions.resetEditing,
- {},
- {},
- [
- {
- type: types.RESET_EDITING,
- },
- ],
- [{ type: 'fetchVariables' }],
- );
- });
- });
-
- describe('setVariableProtected', () => {
- it('commits SET_VARIABLE_PROTECTED mutation', () => {
- testAction(actions.setVariableProtected, {}, {}, [
- {
- type: types.SET_VARIABLE_PROTECTED,
- },
- ]);
- });
- });
-
- describe('deleteVariable', () => {
- it('dispatch correct actions on successful deleted variable', () => {
- mock.onPatch(state.endpoint).reply(200);
-
- return testAction(
- actions.deleteVariable,
- {},
- state,
- [],
- [
- { type: 'requestDeleteVariable' },
- { type: 'receiveDeleteVariableSuccess' },
- { type: 'fetchVariables' },
- ],
- );
- });
-
- it('should show flash error and set error in state on delete failure', async () => {
- mock.onPatch(state.endpoint).reply(500, '');
-
- await testAction(
- actions.deleteVariable,
- {},
- state,
- [],
- [
- { type: 'requestDeleteVariable' },
- {
- type: 'receiveDeleteVariableError',
- payload: payloadError,
- },
- ],
- );
- expect(createAlert).toHaveBeenCalled();
- });
- });
-
- describe('updateVariable', () => {
- it('dispatch correct actions on successful updated variable', () => {
- mock.onPatch(state.endpoint).reply(200);
-
- return testAction(
- actions.updateVariable,
- {},
- state,
- [],
- [
- { type: 'requestUpdateVariable' },
- { type: 'receiveUpdateVariableSuccess' },
- { type: 'fetchVariables' },
- ],
- );
- });
-
- it('should show flash error and set error in state on update failure', async () => {
- mock.onPatch(state.endpoint).reply(500, '');
-
- await testAction(
- actions.updateVariable,
- mockVariable,
- state,
- [],
- [
- { type: 'requestUpdateVariable' },
- {
- type: 'receiveUpdateVariableError',
- payload: payloadError,
- },
- ],
- );
- expect(createAlert).toHaveBeenCalled();
- });
- });
-
- describe('addVariable', () => {
- it('dispatch correct actions on successful added variable', () => {
- mock.onPatch(state.endpoint).reply(200);
-
- return testAction(
- actions.addVariable,
- {},
- state,
- [],
- [
- { type: 'requestAddVariable' },
- { type: 'receiveAddVariableSuccess' },
- { type: 'fetchVariables' },
- ],
- );
- });
-
- it('should show flash error and set error in state on add failure', async () => {
- mock.onPatch(state.endpoint).reply(500, '');
-
- await testAction(
- actions.addVariable,
- {},
- state,
- [],
- [
- { type: 'requestAddVariable' },
- {
- type: 'receiveAddVariableError',
- payload: payloadError,
- },
- ],
- );
- expect(createAlert).toHaveBeenCalled();
- });
- });
-
- describe('fetchVariables', () => {
- it('dispatch correct actions on fetchVariables', () => {
- mock.onGet(state.endpoint).reply(200, { variables: mockData.mockVariables });
-
- return testAction(
- actions.fetchVariables,
- {},
- state,
- [],
- [
- { type: 'requestVariables' },
- {
- type: 'receiveVariablesSuccess',
- payload: prepareDataForDisplay(mockData.mockVariables),
- },
- ],
- );
- });
-
- it('should show flash error and set error in state on fetch variables failure', async () => {
- mock.onGet(state.endpoint).reply(500);
-
- await testAction(actions.fetchVariables, {}, state, [], [{ type: 'requestVariables' }]);
- expect(createAlert).toHaveBeenCalledWith({
- message: 'There was an error fetching the variables.',
- });
- });
- });
-
- describe('fetchEnvironments', () => {
- it('dispatch correct actions on fetchEnvironments', () => {
- Api.environments = jest.fn().mockResolvedValue({ data: mockData.mockEnvironments });
-
- return testAction(
- actions.fetchEnvironments,
- {},
- state,
- [],
- [
- { type: 'requestEnvironments' },
- {
- type: 'receiveEnvironmentsSuccess',
- payload: prepareEnvironments(mockData.mockEnvironments),
- },
- ],
- );
- });
-
- it('should show flash error and set error in state on fetch environments failure', async () => {
- Api.environments = jest.fn().mockRejectedValue();
-
- await testAction(actions.fetchEnvironments, {}, state, [], [{ type: 'requestEnvironments' }]);
-
- expect(createAlert).toHaveBeenCalledWith({
- message: 'There was an error fetching the environments information.',
- });
- });
- });
-
- describe('Update variable values', () => {
- it('updateVariableKey', () => {
- testAction(
- actions.updateVariableKey,
- { key: mockVariable.key },
- {},
- [
- {
- type: types.UPDATE_VARIABLE_KEY,
- payload: mockVariable.key,
- },
- ],
- [],
- );
- });
-
- it('updateVariableValue', () => {
- testAction(
- actions.updateVariableValue,
- { secret_value: mockVariable.value },
- {},
- [
- {
- type: types.UPDATE_VARIABLE_VALUE,
- payload: mockVariable.value,
- },
- ],
- [],
- );
- });
-
- it('updateVariableType', () => {
- testAction(
- actions.updateVariableType,
- { variable_type: mockVariable.variable_type },
- {},
- [{ type: types.UPDATE_VARIABLE_TYPE, payload: mockVariable.variable_type }],
- [],
- );
- });
-
- it('updateVariableProtected', () => {
- testAction(
- actions.updateVariableProtected,
- { protected_variable: mockVariable.protected },
- {},
- [{ type: types.UPDATE_VARIABLE_PROTECTED, payload: mockVariable.protected }],
- [],
- );
- });
-
- it('updateVariableMasked', () => {
- testAction(
- actions.updateVariableMasked,
- { masked: mockVariable.masked },
- {},
- [{ type: types.UPDATE_VARIABLE_MASKED, payload: mockVariable.masked }],
- [],
- );
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/store/getters_spec.js b/spec/frontend/ci_variable_list/store/getters_spec.js
deleted file mode 100644
index 92f22b18763..00000000000
--- a/spec/frontend/ci_variable_list/store/getters_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as getters from '~/ci_variable_list/store/getters';
-import mockData from '../services/mock_data';
-
-describe('Ci variable getters', () => {
- describe('joinedEnvironments', () => {
- it('should join fetched environments with variable environment scopes', () => {
- const state = {
- environments: ['All (default)', 'staging', 'deployment', 'prod'],
- variables: mockData.mockVariableScopes,
- };
-
- expect(getters.joinedEnvironments(state)).toEqual([
- 'All (default)',
- 'deployment',
- 'prod',
- 'production',
- 'staging',
- ]);
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/store/mutations_spec.js b/spec/frontend/ci_variable_list/store/mutations_spec.js
deleted file mode 100644
index c7d07ead09b..00000000000
--- a/spec/frontend/ci_variable_list/store/mutations_spec.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import * as types from '~/ci_variable_list/store/mutation_types';
-import mutations from '~/ci_variable_list/store/mutations';
-import state from '~/ci_variable_list/store/state';
-
-describe('CI variable list mutations', () => {
- let stateCopy;
-
- beforeEach(() => {
- stateCopy = state();
- });
-
- describe('TOGGLE_VALUES', () => {
- it('should toggle state', () => {
- const valuesHidden = false;
-
- mutations[types.TOGGLE_VALUES](stateCopy, valuesHidden);
-
- expect(stateCopy.valuesHidden).toEqual(valuesHidden);
- });
- });
-
- describe('VARIABLE_BEING_EDITED', () => {
- it('should set the variable that is being edited', () => {
- mutations[types.VARIABLE_BEING_EDITED](stateCopy);
-
- expect(stateCopy.variableBeingEdited).toBe(true);
- });
- });
-
- describe('RESET_EDITING', () => {
- it('should reset variableBeingEdited to false', () => {
- mutations[types.RESET_EDITING](stateCopy);
-
- expect(stateCopy.variableBeingEdited).toBe(false);
- });
- });
-
- describe('CLEAR_MODAL', () => {
- it('should clear modal state', () => {
- const modalState = {
- variable_type: 'Variable',
- key: '',
- secret_value: '',
- protected_variable: false,
- masked: false,
- environment_scope: 'All (default)',
- };
-
- mutations[types.CLEAR_MODAL](stateCopy);
-
- expect(stateCopy.variable).toEqual(modalState);
- });
- });
-
- describe('RECEIVE_ENVIRONMENTS_SUCCESS', () => {
- it('should set environments', () => {
- const environments = ['env1', 'env2'];
-
- mutations[types.RECEIVE_ENVIRONMENTS_SUCCESS](stateCopy, environments);
-
- expect(stateCopy.environments).toEqual(['All (default)', 'env1', 'env2']);
- });
- });
-
- describe('SET_ENVIRONMENT_SCOPE', () => {
- const environment = 'production';
-
- it('should set environment scope on variable', () => {
- mutations[types.SET_ENVIRONMENT_SCOPE](stateCopy, environment);
-
- expect(stateCopy.variable.environment_scope).toBe('production');
- });
- });
-
- describe('ADD_WILD_CARD_SCOPE', () => {
- it('should add wild card scope to environments array and sort', () => {
- stateCopy.environments = ['dev', 'staging'];
- mutations[types.ADD_WILD_CARD_SCOPE](stateCopy, 'production');
-
- expect(stateCopy.environments).toEqual(['dev', 'production', 'staging']);
- });
- });
-
- describe('SET_VARIABLE_PROTECTED', () => {
- it('should set protected value to true', () => {
- mutations[types.SET_VARIABLE_PROTECTED](stateCopy);
-
- expect(stateCopy.variable.protected_variable).toBe(true);
- });
- });
-
- describe('UPDATE_VARIABLE_KEY', () => {
- it('should update variable key value', () => {
- const key = 'new_var';
- mutations[types.UPDATE_VARIABLE_KEY](stateCopy, key);
-
- expect(stateCopy.variable.key).toBe(key);
- });
- });
-
- describe('UPDATE_VARIABLE_VALUE', () => {
- it('should update variable value', () => {
- const value = 'variable_value';
- mutations[types.UPDATE_VARIABLE_VALUE](stateCopy, value);
-
- expect(stateCopy.variable.secret_value).toBe(value);
- });
- });
-
- describe('UPDATE_VARIABLE_TYPE', () => {
- it('should update variable type value', () => {
- const type = 'File';
- mutations[types.UPDATE_VARIABLE_TYPE](stateCopy, type);
-
- expect(stateCopy.variable.variable_type).toBe(type);
- });
- });
-
- describe('UPDATE_VARIABLE_PROTECTED', () => {
- it('should update variable protected value', () => {
- const protectedValue = true;
- mutations[types.UPDATE_VARIABLE_PROTECTED](stateCopy, protectedValue);
-
- expect(stateCopy.variable.protected_variable).toBe(protectedValue);
- });
- });
-
- describe('UPDATE_VARIABLE_MASKED', () => {
- it('should update variable masked value', () => {
- const masked = true;
- mutations[types.UPDATE_VARIABLE_MASKED](stateCopy, masked);
-
- expect(stateCopy.variable.masked).toBe(masked);
- });
- });
-});
diff --git a/spec/frontend/ci_variable_list/store/utils_spec.js b/spec/frontend/ci_variable_list/store/utils_spec.js
deleted file mode 100644
index 5b10370324a..00000000000
--- a/spec/frontend/ci_variable_list/store/utils_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import {
- prepareDataForDisplay,
- prepareEnvironments,
- prepareDataForApi,
-} from '~/ci_variable_list/store/utils';
-import mockData from '../services/mock_data';
-
-describe('CI variables store utils', () => {
- it('prepares ci variables for display', () => {
- expect(prepareDataForDisplay(mockData.mockVariablesApi)).toStrictEqual(
- mockData.mockVariablesDisplay,
- );
- });
-
- it('prepares single ci variable for api', () => {
- expect(prepareDataForApi(mockData.mockVariablesDisplay[0])).toStrictEqual({
- environment_scope: '*',
- id: 113,
- key: 'test_var',
- masked: 'false',
- protected: 'false',
- secret_value: 'test_val',
- value: 'test_val',
- variable_type: 'env_var',
- });
-
- expect(prepareDataForApi(mockData.mockVariablesDisplay[1])).toStrictEqual({
- environment_scope: '*',
- id: 114,
- key: 'test_var_2',
- masked: 'false',
- protected: 'false',
- secret_value: 'test_val_2',
- value: 'test_val_2',
- variable_type: 'file',
- });
- });
-
- it('prepares single ci variable for delete', () => {
- expect(prepareDataForApi(mockData.mockVariablesDisplay[0], true)).toHaveProperty(
- '_destroy',
- true,
- );
- });
-
- it('prepares environments for display', () => {
- expect(prepareEnvironments(mockData.mockEnvironments)).toStrictEqual(['staging', 'production']);
- });
-});