summaryrefslogtreecommitdiff
path: root/spec/frontend/integrations/edit/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/integrations/edit/components')
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js81
-rw-r--r--spec/frontend/integrations/edit/components/integration_forms/section_spec.js109
-rw-r--r--spec/frontend/integrations/edit/components/trigger_field_spec.js31
3 files changed, 157 insertions, 64 deletions
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 4b49e492880..383dfb36aa5 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlBadge, GlForm } from '@gitlab/ui';
+import { GlAlert, GlForm } from '@gitlab/ui';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
@@ -11,18 +11,16 @@ import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
import IntegrationForm from '~/integrations/edit/components/integration_form.vue';
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
-import IntegrationSectionConnection from '~/integrations/edit/components/sections/connection.vue';
import IntegrationFormActions from '~/integrations/edit/components/integration_form_actions.vue';
+import IntegrationFormSection from '~/integrations/edit/components/integration_forms/section.vue';
import {
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
INTEGRATION_FORM_TYPE_SLACK,
- billingPlans,
- billingPlanNames,
} from '~/integrations/constants';
import { createStore } from '~/integrations/edit/store';
-import httpStatus from '~/lib/utils/http_status';
+import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import {
mockIntegrationProps,
@@ -73,15 +71,11 @@ describe('IntegrationForm', () => {
const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox);
const findTriggerFields = () => wrapper.findComponent(TriggerFields);
const findAlert = () => wrapper.findComponent(GlAlert);
- const findGlBadge = () => wrapper.findComponent(GlBadge);
const findGlForm = () => wrapper.findComponent(GlForm);
const findRedirectToField = () => wrapper.findByTestId('redirect-to-field');
const findDynamicField = () => wrapper.findComponent(DynamicField);
const findAllDynamicFields = () => wrapper.findAllComponents(DynamicField);
- const findAllSections = () => wrapper.findAllByTestId('integration-section');
- const findConnectionSection = () => findAllSections().at(0);
- const findConnectionSectionComponent = () =>
- findConnectionSection().findComponent(IntegrationSectionConnection);
+ const findAllSections = () => wrapper.findAllComponents(IntegrationFormSection);
const findHelpHtml = () => wrapper.findByTestId('help-html');
const findFormActions = () => wrapper.findComponent(IntegrationFormActions);
@@ -215,54 +209,13 @@ describe('IntegrationForm', () => {
beforeEach(() => {
createComponent({
customStateProps: {
- sections: [mockSectionConnection],
- },
- });
- });
-
- it('renders the expected number of sections', () => {
- expect(findAllSections().length).toBe(1);
- });
-
- it('renders title, description and the correct dynamic component', () => {
- const connectionSection = findConnectionSection();
-
- expect(connectionSection.find('h4').text()).toBe(mockSectionConnection.title);
- expect(connectionSection.find('p').text()).toBe(mockSectionConnection.description);
- expect(findGlBadge().exists()).toBe(false);
- expect(findConnectionSectionComponent().exists()).toBe(true);
- });
-
- it('renders GlBadge when `plan` is present', () => {
- createComponent({
- customStateProps: {
sections: [mockSectionConnection, mockSectionJiraIssues],
},
});
-
- expect(findGlBadge().exists()).toBe(true);
- expect(findGlBadge().text()).toMatchInterpolatedText(billingPlanNames[billingPlans.PREMIUM]);
});
- it('passes only fields with section type', () => {
- const sectionFields = [
- { name: 'username', type: 'text', section: mockSectionConnection.type },
- { name: 'API token', type: 'password', section: mockSectionConnection.type },
- ];
-
- const nonSectionFields = [
- { name: 'branch', type: 'text' },
- { name: 'labels', type: 'select' },
- ];
-
- createComponent({
- customStateProps: {
- sections: [mockSectionConnection],
- fields: [...sectionFields, ...nonSectionFields],
- },
- });
-
- expect(findConnectionSectionComponent().props('fields')).toEqual(sectionFields);
+ it('renders the expected number of sections', () => {
+ expect(findAllSections()).toHaveLength(2);
});
describe.each`
@@ -281,7 +234,8 @@ describe('IntegrationForm', () => {
},
});
- findConnectionSectionComponent().vm.$emit('toggle-integration-active', formActive);
+ const section = findAllSections().at(0);
+ section.vm.$emit('toggle-integration-active', formActive);
});
it(`sets noValidate to ${novalidate}`, () => {
@@ -290,7 +244,7 @@ describe('IntegrationForm', () => {
},
);
- describe('when IntegrationSectionConnection emits `request-jira-issue-types` event', () => {
+ describe('when section emits `request-jira-issue-types` event', () => {
beforeEach(() => {
jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('form'));
@@ -302,7 +256,8 @@ describe('IntegrationForm', () => {
mountFn: mountExtended,
});
- findConnectionSectionComponent().vm.$emit('request-jira-issue-types');
+ const section = findAllSections().at(0);
+ section.vm.$emit('request-jira-issue-types');
});
it('dispatches `requestJiraIssueTypes` action', () => {
@@ -456,11 +411,11 @@ describe('IntegrationForm', () => {
});
describe.each`
- scenario | replyStatus | errorMessage | serviceResponse | expectToast | expectSentry
- ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
- ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${undefined} | ${'an error'} | ${false}
- ${'when "test settings" returns an error with details'} | ${httpStatus.OK} | ${'an error.'} | ${'extra info'} | ${'an error. extra info'} | ${false}
- ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
+ scenario | replyStatus | errorMessage | serviceResponse | expectToast | expectSentry
+ ${'when "test settings" request fails'} | ${HTTP_STATUS_INTERNAL_SERVER_ERROR} | ${undefined} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
+ ${'when "test settings" returns an error'} | ${HTTP_STATUS_OK} | ${'an error'} | ${undefined} | ${'an error'} | ${false}
+ ${'when "test settings" returns an error with details'} | ${HTTP_STATUS_OK} | ${'an error.'} | ${'extra info'} | ${'an error. extra info'} | ${false}
+ ${'when "test settings" succeeds'} | ${HTTP_STATUS_OK} | ${undefined} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
`(
'$scenario',
({ replyStatus, errorMessage, serviceResponse, expectToast, expectSentry }) => {
@@ -491,7 +446,7 @@ describe('IntegrationForm', () => {
const mockResetPath = '/reset';
beforeEach(async () => {
- mockAxios.onPost(mockResetPath).replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
+ mockAxios.onPost(mockResetPath).replyOnce(HTTP_STATUS_INTERNAL_SERVER_ERROR);
createComponent({
customStateProps: {
resetPath: mockResetPath,
@@ -526,7 +481,7 @@ describe('IntegrationForm', () => {
describe('when "reset settings" succeeds', () => {
beforeEach(async () => {
- mockAxios.onPost(mockResetPath).replyOnce(httpStatus.OK);
+ mockAxios.onPost(mockResetPath).replyOnce(HTTP_STATUS_OK);
createComponent({
customStateProps: {
resetPath: mockResetPath,
diff --git a/spec/frontend/integrations/edit/components/integration_forms/section_spec.js b/spec/frontend/integrations/edit/components/integration_forms/section_spec.js
new file mode 100644
index 00000000000..5f82941778e
--- /dev/null
+++ b/spec/frontend/integrations/edit/components/integration_forms/section_spec.js
@@ -0,0 +1,109 @@
+import { GlBadge } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { billingPlans, billingPlanNames } from '~/integrations/constants';
+import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
+import IntegrationFormSection from '~/integrations/edit/components/integration_forms/section.vue';
+import IntegrationSectionConnection from '~/integrations/edit/components/sections/connection.vue';
+import { createStore } from '~/integrations/edit/store';
+import {
+ mockIntegrationProps,
+ mockSectionConnection,
+ mockSectionJiraIssues,
+} from '../../mock_data';
+
+describe('Integration Form Section', () => {
+ let wrapper;
+
+ const defaultProps = {
+ section: mockSectionConnection,
+ isValidated: false,
+ };
+
+ const createComponent = ({
+ customStateProps = {},
+ props = {},
+ mountFn = shallowMountExtended,
+ } = {}) => {
+ const store = createStore({
+ customState: {
+ ...mockIntegrationProps,
+ ...customStateProps,
+ },
+ });
+
+ wrapper = mountFn(IntegrationFormSection, {
+ store,
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ stubs: {
+ IntegrationSectionConnection,
+ },
+ });
+ };
+
+ const findGlBadge = () => wrapper.findComponent(GlBadge);
+ const findFieldsComponent = () => wrapper.findComponent(IntegrationSectionConnection);
+ const findAllDynamicFields = () => wrapper.findAllComponents(DynamicField);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders title, description and the correct dynamic component', () => {
+ expect(wrapper.findByText(mockSectionConnection.title).exists()).toBe(true);
+ expect(wrapper.findByText(mockSectionConnection.description).exists()).toBe(true);
+ expect(findGlBadge().exists()).toBe(false);
+ });
+
+ it('renders GlBadge when `plan` is present', () => {
+ createComponent({
+ props: {
+ section: mockSectionJiraIssues,
+ },
+ });
+
+ expect(findGlBadge().exists()).toBe(true);
+ expect(findGlBadge().text()).toMatchInterpolatedText(billingPlanNames[billingPlans.PREMIUM]);
+ });
+
+ it('renders only fields for this section type', () => {
+ const sectionFields = [
+ { name: 'username', type: 'text', section: mockSectionConnection.type },
+ { name: 'API token', type: 'password', section: mockSectionConnection.type },
+ ];
+
+ const nonSectionFields = [{ name: 'branch', type: 'text' }];
+
+ createComponent({
+ customStateProps: {
+ fields: [...sectionFields, ...nonSectionFields],
+ },
+ });
+
+ expect(findAllDynamicFields()).toHaveLength(2);
+ sectionFields.forEach((field, index) => {
+ expect(findAllDynamicFields().at(index).props('name')).toBe(field.name);
+ });
+ });
+
+ describe('events proxy from the section', () => {
+ let section;
+ const dummyPayload = 'foo';
+
+ beforeEach(() => {
+ section = findFieldsComponent();
+ });
+
+ it('toggle-integration-active', () => {
+ section.vm.$emit('toggle-integration-active', dummyPayload);
+ expect(wrapper.emitted('toggle-integration-active')).toEqual([[dummyPayload]]);
+ });
+
+ it('request-jira-issue-types', () => {
+ section.vm.$emit('request-jira-issue-types', dummyPayload);
+ expect(wrapper.emitted('request-jira-issue-types')).toEqual([[dummyPayload]]);
+ });
+ });
+});
diff --git a/spec/frontend/integrations/edit/components/trigger_field_spec.js b/spec/frontend/integrations/edit/components/trigger_field_spec.js
index 6a68337813e..ed0b3324708 100644
--- a/spec/frontend/integrations/edit/components/trigger_field_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_field_spec.js
@@ -1,6 +1,6 @@
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
-import { GlFormCheckbox } from '@gitlab/ui';
+import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import TriggerField from '~/integrations/edit/components/trigger_field.vue';
import { integrationTriggerEventTitles } from '~/integrations/constants';
@@ -10,7 +10,9 @@ describe('TriggerField', () => {
const defaultProps = {
event: { name: 'push_events' },
+ type: 'gitlab_slack_application',
};
+ const mockField = { name: 'push_channel' };
const createComponent = ({ props = {}, isInheriting = false } = {}) => {
wrapper = shallowMount(TriggerField, {
@@ -26,6 +28,7 @@ describe('TriggerField', () => {
});
const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox);
+ const findGlFormInput = () => wrapper.findComponent(GlFormInput);
const findHiddenInput = () => wrapper.find('input[type="hidden"]');
describe('template', () => {
@@ -55,6 +58,32 @@ describe('TriggerField', () => {
expect(findHiddenInput().attributes('value')).toBe('false');
});
+ it('renders hidden GlFormInput', () => {
+ createComponent({
+ props: {
+ event: { name: 'push_events', field: mockField },
+ },
+ });
+
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().isVisible()).toBe(false);
+ });
+
+ describe('checkbox is selected', () => {
+ it('renders visible GlFormInput', async () => {
+ createComponent({
+ props: {
+ event: { name: 'push_events', field: mockField },
+ },
+ });
+
+ await findGlFormCheckbox().vm.$emit('input', true);
+
+ expect(findGlFormInput().exists()).toBe(true);
+ expect(findGlFormInput().isVisible()).toBe(true);
+ });
+ });
+
it('toggles value of hidden input on checkbox input', async () => {
createComponent({
props: { event: { name: 'push_events', value: true } },