gitlab-org--gitlab-foss/spec/frontend/security_configuration/manage_sast_spec.js

137 lines
3.9 KiB
JavaScript

import { GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { redirectTo } from '~/lib/utils/url_utility';
import ManageSast from '~/security_configuration/components/manage_sast.vue';
import configureSastMutation from '~/security_configuration/graphql/configure_sast.mutation.graphql';
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
}));
Vue.use(VueApollo);
describe('Manage Sast Component', () => {
let wrapper;
const findButton = () => wrapper.findComponent(GlButton);
const successHandler = async () => {
return {
data: {
configureSast: {
successPath: 'testSuccessPath',
errors: [],
__typename: 'ConfigureSastPayload',
},
},
};
};
const noSuccessPathHandler = async () => {
return {
data: {
configureSast: {
successPath: '',
errors: [],
__typename: 'ConfigureSastPayload',
},
},
};
};
const errorHandler = async () => {
return {
data: {
configureSast: {
successPath: 'testSuccessPath',
errors: ['foo'],
__typename: 'ConfigureSastPayload',
},
},
};
};
const pendingHandler = () => new Promise(() => {});
function createMockApolloProvider(handler) {
const requestHandlers = [[configureSastMutation, handler]];
return createMockApollo(requestHandlers);
}
function createComponent(options = {}) {
const { mockApollo } = options;
wrapper = extendedWrapper(
mount(ManageSast, {
apolloProvider: mockApollo,
}),
);
}
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('should render Button with correct text', () => {
createComponent();
expect(findButton().text()).toContain('Configure via Merge Request');
});
describe('given a successful response', () => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(successHandler);
createComponent({ mockApollo });
});
it('should call redirect helper with correct value', async () => {
await wrapper.trigger('click');
await waitForPromises();
expect(redirectTo).toHaveBeenCalledTimes(1);
expect(redirectTo).toHaveBeenCalledWith('testSuccessPath');
// This is done for UX reasons. If the loading prop is set to false
// on success, then there's a period where the button is clickable
// again. Instead, we want the button to display a loading indicator
// for the remainder of the lifetime of the page (i.e., until the
// browser can start painting the new page it's been redirected to).
expect(findButton().props().loading).toBe(true);
});
});
describe('given a pending response', () => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(pendingHandler);
createComponent({ mockApollo });
});
it('renders spinner correctly', async () => {
expect(findButton().props('loading')).toBe(false);
await wrapper.trigger('click');
await waitForPromises();
expect(findButton().props('loading')).toBe(true);
});
});
describe.each`
handler | message
${noSuccessPathHandler} | ${'SAST merge request creation mutation failed'}
${errorHandler} | ${'foo'}
`('given an error response', ({ handler, message }) => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(handler);
createComponent({ mockApollo });
});
it('should catch and emit error', async () => {
await wrapper.trigger('click');
await waitForPromises();
expect(wrapper.emitted('error')).toEqual([[message]]);
expect(findButton().props('loading')).toBe(false);
});
});
});