312 lines
10 KiB
JavaScript
312 lines
10 KiB
JavaScript
|
import { GlAlert, GlFormInput, GlToggle, GlLoadingIcon } from '@gitlab/ui';
|
||
|
import Vue from 'vue';
|
||
|
import VueApollo from 'vue-apollo';
|
||
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||
|
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||
|
import waitForPromises from 'helpers/wait_for_promises';
|
||
|
import { createAlert } from '~/flash';
|
||
|
import InboundTokenAccess from '~/token_access/components/inbound_token_access.vue';
|
||
|
import inboundAddProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_add_project_ci_job_token_scope.mutation.graphql';
|
||
|
import inboundRemoveProjectCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_remove_project_ci_job_token_scope.mutation.graphql';
|
||
|
import inboundUpdateCIJobTokenScopeMutation from '~/token_access/graphql/mutations/inbound_update_ci_job_token_scope.mutation.graphql';
|
||
|
import inboundGetCIJobTokenScopeQuery from '~/token_access/graphql/queries/inbound_get_ci_job_token_scope.query.graphql';
|
||
|
import inboundGetProjectsWithCIJobTokenScopeQuery from '~/token_access/graphql/queries/inbound_get_projects_with_ci_job_token_scope.query.graphql';
|
||
|
import {
|
||
|
inboundJobTokenScopeEnabledResponse,
|
||
|
inboundJobTokenScopeDisabledResponse,
|
||
|
inboundProjectsWithScopeResponse,
|
||
|
inboundAddProjectSuccessResponse,
|
||
|
inboundRemoveProjectSuccess,
|
||
|
inboundUpdateScopeSuccessResponse,
|
||
|
} from './mock_data';
|
||
|
|
||
|
const projectPath = 'root/my-repo';
|
||
|
const message = 'An error occurred';
|
||
|
const error = new Error(message);
|
||
|
|
||
|
Vue.use(VueApollo);
|
||
|
|
||
|
jest.mock('~/flash');
|
||
|
|
||
|
describe('TokenAccess component', () => {
|
||
|
let wrapper;
|
||
|
|
||
|
const inboundJobTokenScopeEnabledResponseHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundJobTokenScopeEnabledResponse);
|
||
|
const inboundJobTokenScopeDisabledResponseHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundJobTokenScopeDisabledResponse);
|
||
|
const inboundProjectsWithScopeResponseHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundProjectsWithScopeResponse);
|
||
|
const inboundAddProjectSuccessResponseHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundAddProjectSuccessResponse);
|
||
|
const inboundRemoveProjectSuccessHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundRemoveProjectSuccess);
|
||
|
const inboundUpdateScopeSuccessResponseHandler = jest
|
||
|
.fn()
|
||
|
.mockResolvedValue(inboundUpdateScopeSuccessResponse);
|
||
|
const failureHandler = jest.fn().mockRejectedValue(error);
|
||
|
|
||
|
const findToggle = () => wrapper.findComponent(GlToggle);
|
||
|
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||
|
const findAddProjectBtn = () => wrapper.findByRole('button', { name: 'Add project' });
|
||
|
const findCancelBtn = () => wrapper.findByRole('button', { name: 'Cancel' });
|
||
|
const findProjectInput = () => wrapper.findComponent(GlFormInput);
|
||
|
const findRemoveProjectBtn = () => wrapper.findByRole('button', { name: 'Remove access' });
|
||
|
const findTokenDisabledAlert = () => wrapper.findComponent(GlAlert);
|
||
|
|
||
|
const createMockApolloProvider = (requestHandlers) => {
|
||
|
return createMockApollo(requestHandlers);
|
||
|
};
|
||
|
|
||
|
const createComponent = (requestHandlers, mountFn = shallowMountExtended) => {
|
||
|
wrapper = mountFn(InboundTokenAccess, {
|
||
|
provide: {
|
||
|
fullPath: projectPath,
|
||
|
},
|
||
|
apolloProvider: createMockApolloProvider(requestHandlers),
|
||
|
data() {
|
||
|
return {
|
||
|
targetProjectPath: 'root/test',
|
||
|
};
|
||
|
},
|
||
|
});
|
||
|
};
|
||
|
|
||
|
describe('loading state', () => {
|
||
|
it('shows loading state while waiting on query to resolve', async () => {
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
]);
|
||
|
|
||
|
expect(findLoadingIcon().exists()).toBe(true);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findLoadingIcon().exists()).toBe(false);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('fetching projects and scope', () => {
|
||
|
it('fetches projects and scope correctly', () => {
|
||
|
const expectedVariables = {
|
||
|
fullPath: 'root/my-repo',
|
||
|
};
|
||
|
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
]);
|
||
|
|
||
|
expect(inboundJobTokenScopeEnabledResponseHandler).toHaveBeenCalledWith(expectedVariables);
|
||
|
expect(inboundProjectsWithScopeResponseHandler).toHaveBeenCalledWith(expectedVariables);
|
||
|
});
|
||
|
|
||
|
it('handles fetch projects error correctly', async () => {
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, failureHandler],
|
||
|
]);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(createAlert).toHaveBeenCalledWith({
|
||
|
message: 'There was a problem fetching the projects',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('handles fetch scope error correctly', async () => {
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, failureHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
]);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(createAlert).toHaveBeenCalledWith({
|
||
|
message: 'There was a problem fetching the job token scope value',
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('toggle', () => {
|
||
|
it('the toggle is on and the alert is hidden', async () => {
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
]);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(true);
|
||
|
expect(findTokenDisabledAlert().exists()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('the toggle is off and the alert is visible', async () => {
|
||
|
createComponent([
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeDisabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
]);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(false);
|
||
|
expect(findTokenDisabledAlert().exists()).toBe(true);
|
||
|
});
|
||
|
|
||
|
describe('update ci job token scope', () => {
|
||
|
it('calls inboundUpdateCIJobTokenScopeMutation mutation', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundUpdateCIJobTokenScopeMutation, inboundUpdateScopeSuccessResponseHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(true);
|
||
|
|
||
|
findToggle().vm.$emit('change', false);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(false);
|
||
|
expect(inboundUpdateScopeSuccessResponseHandler).toHaveBeenCalledWith({
|
||
|
input: {
|
||
|
fullPath: 'root/my-repo',
|
||
|
inboundJobTokenScopeEnabled: false,
|
||
|
},
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('handles update scope error correctly', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeDisabledResponseHandler],
|
||
|
[inboundUpdateCIJobTokenScopeMutation, failureHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(false);
|
||
|
|
||
|
findToggle().vm.$emit('change', true);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findToggle().props('value')).toBe(false);
|
||
|
expect(createAlert).toHaveBeenCalledWith({ message });
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('add project', () => {
|
||
|
it('calls add project mutation', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
[inboundAddProjectCIJobTokenScopeMutation, inboundAddProjectSuccessResponseHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
findAddProjectBtn().trigger('click');
|
||
|
|
||
|
expect(inboundAddProjectSuccessResponseHandler).toHaveBeenCalledWith({
|
||
|
projectPath,
|
||
|
targetProjectPath: 'root/test',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('add project handles error correctly', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
[inboundAddProjectCIJobTokenScopeMutation, failureHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
findAddProjectBtn().trigger('click');
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(createAlert).toHaveBeenCalledWith({ message });
|
||
|
});
|
||
|
|
||
|
it('clicking cancel clears target path', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(findProjectInput().element.value).toBe('root/test');
|
||
|
|
||
|
await findCancelBtn().trigger('click');
|
||
|
|
||
|
expect(findProjectInput().element.value).toBe('');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('remove project', () => {
|
||
|
it('calls remove project mutation', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
[inboundRemoveProjectCIJobTokenScopeMutation, inboundRemoveProjectSuccessHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
findRemoveProjectBtn().trigger('click');
|
||
|
|
||
|
expect(inboundRemoveProjectSuccessHandler).toHaveBeenCalledWith({
|
||
|
projectPath,
|
||
|
targetProjectPath: 'root/ci-project',
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('remove project handles error correctly', async () => {
|
||
|
createComponent(
|
||
|
[
|
||
|
[inboundGetCIJobTokenScopeQuery, inboundJobTokenScopeEnabledResponseHandler],
|
||
|
[inboundGetProjectsWithCIJobTokenScopeQuery, inboundProjectsWithScopeResponseHandler],
|
||
|
[inboundRemoveProjectCIJobTokenScopeMutation, failureHandler],
|
||
|
],
|
||
|
mountExtended,
|
||
|
);
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
findRemoveProjectBtn().trigger('click');
|
||
|
|
||
|
await waitForPromises();
|
||
|
|
||
|
expect(createAlert).toHaveBeenCalledWith({ message });
|
||
|
});
|
||
|
});
|
||
|
});
|