summaryrefslogtreecommitdiff
path: root/spec/frontend/security_configuration/manage_sast_spec.js
blob: 15a57210246ecb84a78d45e75047c373fcfbdb8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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);
    });
  });
});