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:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 03:08:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-29 03:08:36 +0300
commit1063cd719c0e25df43bf5d2c0ea8e22f112ed225 (patch)
tree0bdd8d0582bb9cd0d2ca5a6d3ea8ca593465a964 /spec/frontend/alerts_settings
parent669f67690a43e9ec7b6d148c6ec1391b379fa16e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/alerts_settings')
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap20
-rw-r--r--spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap47
-rw-r--r--spec/frontend/alerts_settings/alerts_integrations_list_spec.js89
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_new_spec.js59
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_form_old_spec.js206
-rw-r--r--spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js48
-rw-r--r--spec/frontend/alerts_settings/util.js28
7 files changed, 497 insertions, 0 deletions
diff --git a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap
new file mode 100644
index 00000000000..68328ef3518
--- /dev/null
+++ b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_new_spec.js.snap
@@ -0,0 +1,20 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AlertsSettingsFormNew with default values renders the initial template 1`] = `
+"<gl-form-stub class=\\"gl-mt-6\\">
+ <h5 class=\\"gl-font-lg gl-my-5\\">Add new integrations</h5>
+ <gl-form-group-stub id=\\"integration-type\\" label=\\"1. Select integration type\\" label-for=\\"integration-type\\">
+ <gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object],[object Object]\\" value=\\"\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
+ </gl-form-group-stub>
+ <b-collapse-stub tag=\\"div\\" class=\\"gl-mt-3\\">
+ <gl-form-group-stub id=\\"name-integration\\" label=\\"2. Name integration\\" label-for=\\"name-integration\\">
+ <b-form-input-stub id=\\"name-integration\\" value=\\"\\" placeholder=\\"Enter integration name\\" debounce=\\"0\\" type=\\"text\\" class=\\"gl-form-input\\"></b-form-input-stub>
+ </gl-form-group-stub>
+ <div class=\\"gl-display-flex gl-justify-content-end\\">
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"reset\\" class=\\"gl-mr-3 js-no-auto-disable\\">Cancel</gl-button-stub>
+ <gl-button-stub category=\\"secondary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"submit\\" class=\\"gl-mr-1 js-no-auto-disable\\">Save and test payload</gl-button-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" type=\\"submit\\" class=\\"js-no-auto-disable\\">Save integration</gl-button-stub>
+ </div>
+ </b-collapse-stub>
+</gl-form-stub>"
+`;
diff --git a/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap
new file mode 100644
index 00000000000..b7b4d96548e
--- /dev/null
+++ b/spec/frontend/alerts_settings/__snapshots__/alerts_settings_form_old_spec.js.snap
@@ -0,0 +1,47 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
+"<gl-form-stub>
+ <h5 class=\\"gl-font-lg gl-my-5\\"></h5>
+ <!---->
+ <div data-testid=\\"alert-settings-description\\">
+ <p>
+ <gl-sprintf-stub message=\\"You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page.\\"></gl-sprintf-stub>
+ </p>
+ <p>
+ <gl-sprintf-stub message=\\"Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint.\\"></gl-sprintf-stub>
+ </p>
+ </div>
+ <gl-form-group-stub label-for=\\"integration-type\\" label=\\"Integration\\">
+ <gl-form-select-stub id=\\"integration-type\\" options=\\"[object Object],[object Object],[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"generic\\"></gl-form-select-stub> <span class=\\"gl-text-gray-500\\"><gl-sprintf-stub message=\\"Learn more about our our upcoming %{linkStart}integrations%{linkEnd}\\"></gl-sprintf-stub></span>
+ </gl-form-group-stub>
+ <gl-form-group-stub label=\\"Active\\" label-for=\\"activated\\">
+ <toggle-button-stub id=\\"activated\\"></toggle-button-stub>
+ </gl-form-group-stub>
+ <!---->
+ <gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\">
+ <gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-500\\">
+
+ </span>
+ </gl-form-group-stub>
+ <gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
+ <gl-form-input-group-stub value=\\"abcedfg123\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
+ <gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
+ Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
+ </gl-modal-stub>
+ </gl-form-group-stub>
+ <gl-form-group-stub label=\\"Alert test payload\\" label-for=\\"alert-json\\">
+ <gl-form-textarea-stub noresize=\\"true\\" id=\\"alert-json\\" disabled=\\"true\\" state=\\"true\\" placeholder=\\"Enter test alert JSON....\\" rows=\\"6\\" max-rows=\\"10\\"></gl-form-textarea-stub>
+ </gl-form-group-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
+ <div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between\\">
+ <gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
+ Save changes
+ </gl-button-stub>
+ <gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\">
+ Cancel
+ </gl-button-stub>
+ </div>
+</gl-form-stub>"
+`;
diff --git a/spec/frontend/alerts_settings/alerts_integrations_list_spec.js b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
new file mode 100644
index 00000000000..4377cd0a60d
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_integrations_list_spec.js
@@ -0,0 +1,89 @@
+import { GlTable, GlIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import Tracking from '~/tracking';
+import AlertIntegrationsList, {
+ i18n,
+} from '~/alerts_settings/components/alerts_integrations_list.vue';
+import { trackAlertIntegrationsViewsOptions } from '~/alerts_settings/constants';
+
+const mockIntegrations = [
+ {
+ activated: true,
+ name: 'Integration 1',
+ type: 'HTTP endpoint',
+ },
+ {
+ activated: false,
+ name: 'Integration 2',
+ type: 'HTTP endpoint',
+ },
+];
+
+describe('AlertIntegrationsList', () => {
+ let wrapper;
+
+ function mountComponent(propsData = {}) {
+ wrapper = mount(AlertIntegrationsList, {
+ propsData: {
+ integrations: mockIntegrations,
+ ...propsData,
+ },
+ stubs: {
+ GlIcon: true,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ const findTableComponent = () => wrapper.find(GlTable);
+ const finsStatusCell = () => wrapper.findAll('[data-testid="integration-activated-status"]');
+
+ it('renders a table', () => {
+ expect(findTableComponent().exists()).toBe(true);
+ });
+
+ it('renders an empty state when no integrations provided', () => {
+ mountComponent({ integrations: [] });
+ expect(findTableComponent().text()).toContain(i18n.emptyState);
+ });
+
+ describe('integration status', () => {
+ it('enabled', () => {
+ const cell = finsStatusCell().at(0);
+ const activatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.enabled.name);
+ expect(activatedIcon.attributes('name')).toBe('check-circle-filled');
+ expect(activatedIcon.attributes('title')).toBe(i18n.status.enabled.tooltip);
+ });
+
+ it('disabled', () => {
+ const cell = finsStatusCell().at(1);
+ const notActivatedIcon = cell.find(GlIcon);
+ expect(cell.text()).toBe(i18n.status.disabled.name);
+ expect(notActivatedIcon.attributes('name')).toBe('warning-solid');
+ expect(notActivatedIcon.attributes('title')).toBe(i18n.status.disabled.tooltip);
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ mountComponent();
+ });
+
+ it('should track alert list page views', () => {
+ const { category, action } = trackAlertIntegrationsViewsOptions;
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
new file mode 100644
index 00000000000..ae12f6c9bef
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_form_new_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlForm, GlFormSelect, GlCollapse, GlFormInput } from '@gitlab/ui';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_new.vue';
+import { defaultAlertSettingsConfig } from './util';
+
+jest.mock('~/alerts_settings/services');
+
+describe('AlertsSettingsFormNew', () => {
+ let wrapper;
+
+ const createComponent = ({ methods } = {}, data) => {
+ wrapper = shallowMount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ },
+ methods,
+ stubs: { GlCollapse, GlFormInput },
+ });
+ };
+
+ const findForm = () => wrapper.find(GlForm);
+ const findSelect = () => wrapper.find(GlFormSelect);
+ const findFormSteps = () => wrapper.find(GlCollapse);
+ const findFormName = () => wrapper.find(GlFormInput);
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with default values', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the initial template', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('render the initial form with only an integration type dropdown', () => {
+ expect(findForm().exists()).toBe(true);
+ expect(findSelect().exists()).toBe(true);
+ expect(findFormSteps().attributes('visible')).toBeUndefined();
+ });
+
+ it('shows the rest of the form when the dropdown is used', async () => {
+ findSelect().vm.$emit('change', 'prometheus');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findFormName().isVisible()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js b/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js
new file mode 100644
index 00000000000..0fb601b41d5
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_form_old_spec.js
@@ -0,0 +1,206 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlModal, GlAlert } from '@gitlab/ui';
+import AlertsSettingsForm from '~/alerts_settings/components/alerts_settings_form_old.vue';
+import ToggleButton from '~/vue_shared/components/toggle_button.vue';
+import { i18n } from '~/alerts_settings/constants';
+import service from '~/alerts_settings/services';
+import { defaultAlertSettingsConfig } from './util';
+
+jest.mock('~/alerts_settings/services');
+
+describe('AlertsSettingsForm', () => {
+ let wrapper;
+
+ const createComponent = ({ methods } = {}, data) => {
+ wrapper = shallowMount(AlertsSettingsForm, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ },
+ methods,
+ });
+ };
+
+ const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]');
+ const findJsonInput = () => wrapper.find('#alert-json');
+ const findUrl = () => wrapper.find('#url');
+ const findAuthorizationKey = () => wrapper.find('#authorization-key');
+ const findApiUrl = () => wrapper.find('#api-url');
+
+ beforeEach(() => {
+ setFixtures(`
+ <div>
+ <span class="js-service-active-status fa fa-circle" data-value="true"></span>
+ <span class="js-service-active-status fa fa-power-off" data-value="false"></span>
+ </div>`);
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with default values', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders the initial template', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+ });
+
+ describe('reset key', () => {
+ it('triggers resetKey method', () => {
+ const resetKey = jest.fn();
+ const methods = { resetKey };
+ createComponent({ methods });
+
+ wrapper.find(GlModal).vm.$emit('ok');
+
+ expect(resetKey).toHaveBeenCalled();
+ });
+
+ it('updates the authorization key on success', () => {
+ createComponent(
+ {},
+ {
+ authKey: 'newToken',
+ },
+ );
+
+ expect(findAuthorizationKey().attributes('value')).toBe('newToken');
+ });
+
+ it('shows a alert message on error', () => {
+ service.updateGenericKey.mockRejectedValueOnce({});
+
+ createComponent();
+
+ return wrapper.vm.resetKey().then(() => {
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('activate toggle', () => {
+ it('triggers toggleActivated method', () => {
+ const toggleService = jest.fn();
+ const methods = { toggleService };
+ createComponent({ methods });
+
+ wrapper.find(ToggleButton).vm.$emit('change', true);
+ expect(toggleService).toHaveBeenCalled();
+ });
+
+ describe('error is encountered', () => {
+ it('restores previous value', () => {
+ service.updateGenericKey.mockRejectedValueOnce({});
+ createComponent();
+ return wrapper.vm.resetKey().then(() => {
+ expect(wrapper.find(ToggleButton).props('value')).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('prometheus is active', () => {
+ beforeEach(() => {
+ createComponent(
+ {},
+ {
+ selectedIntegration: 'prometheus',
+ },
+ );
+ });
+
+ it('renders a valid "select"', () => {
+ expect(findSelect().exists()).toBe(true);
+ });
+
+ it('shows the API URL input', () => {
+ expect(findApiUrl().exists()).toBe(true);
+ });
+
+ it('shows the correct default API URL', () => {
+ expect(findUrl().attributes('value')).toBe(
+ defaultAlertSettingsConfig.prometheus.prometheusUrl,
+ );
+ });
+ });
+
+ describe('Opsgenie is active', () => {
+ beforeEach(() => {
+ createComponent(
+ {},
+ {
+ selectedIntegration: 'opsgenie',
+ },
+ );
+ });
+
+ it('shows a input for the Opsgenie target URL', () => {
+ expect(findApiUrl().exists()).toBe(true);
+ });
+ });
+
+ describe('trigger test alert', () => {
+ beforeEach(() => {
+ createComponent({});
+ });
+
+ it('should enable the JSON input', () => {
+ expect(findJsonInput().exists()).toBe(true);
+ expect(findJsonInput().props('value')).toBe(null);
+ });
+
+ it('should validate JSON input', async () => {
+ createComponent(true, {
+ testAlertJson: '{ "value": "test" }',
+ });
+
+ findJsonInput().vm.$emit('change');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findJsonInput().attributes('state')).toBe('true');
+ });
+
+ describe('alert service is toggled', () => {
+ describe('error handling', () => {
+ const toggleService = true;
+
+ it('should show generic error', async () => {
+ service.updateGenericActive.mockRejectedValueOnce({});
+
+ createComponent();
+
+ await wrapper.vm.toggleActivated(toggleService);
+ expect(wrapper.vm.active).toBe(false);
+ expect(wrapper.find(GlAlert).attributes('variant')).toBe('danger');
+ expect(wrapper.find(GlAlert).text()).toBe(i18n.errorMsg);
+ });
+
+ it('should show first field specific error when available', async () => {
+ const err1 = "can't be blank";
+ const err2 = 'is not a valid URL';
+ const key = 'api_url';
+ service.updateGenericActive.mockRejectedValueOnce({
+ response: { data: { errors: { [key]: [err1, err2] } } },
+ });
+
+ createComponent();
+
+ await wrapper.vm.toggleActivated(toggleService);
+
+ expect(wrapper.find(GlAlert).text()).toContain(i18n.errorMsg);
+ expect(wrapper.find(GlAlert).text()).toContain(`${key} ${err1}`);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
new file mode 100644
index 00000000000..74f3aa1d995
--- /dev/null
+++ b/spec/frontend/alerts_settings/alerts_settings_wrapper_spec.js
@@ -0,0 +1,48 @@
+import { shallowMount } from '@vue/test-utils';
+import AlertsSettingsWrapper from '~/alerts_settings/components/alerts_settings_wrapper.vue';
+import AlertsSettingsFormOld from '~/alerts_settings/components/alerts_settings_form_old.vue';
+import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_form_new.vue';
+import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
+import { defaultAlertSettingsConfig } from './util';
+
+jest.mock('~/alerts_settings/services');
+
+describe('AlertsSettingsFormWrapper', () => {
+ let wrapper;
+
+ const createComponent = (data = {}, provide = {}) => {
+ wrapper = shallowMount(AlertsSettingsWrapper, {
+ data() {
+ return { ...data };
+ },
+ provide: {
+ ...defaultAlertSettingsConfig,
+ glFeatures: { httpIntegrationsList: false },
+ ...provide,
+ },
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ describe('with default values', () => {
+ it('renders alerts integrations list and old form by default', () => {
+ createComponent();
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(false);
+ });
+
+ it('renders alerts integrations list and new form when httpIntegrationsList feature flag is enabled', () => {
+ createComponent({}, { glFeatures: { httpIntegrationsList: true } });
+ expect(wrapper.find(IntegrationsList).exists()).toBe(true);
+ expect(wrapper.find(AlertsSettingsFormOld).exists()).toBe(false);
+ expect(wrapper.find(AlertsSettingsFormNew).exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/alerts_settings/util.js b/spec/frontend/alerts_settings/util.js
new file mode 100644
index 00000000000..cbb98097b43
--- /dev/null
+++ b/spec/frontend/alerts_settings/util.js
@@ -0,0 +1,28 @@
+const PROMETHEUS_URL = '/prometheus/alerts/notify.json';
+const GENERIC_URL = '/alerts/notify.json';
+const KEY = 'abcedfg123';
+const INVALID_URL = 'http://invalid';
+const ACTIVATED = false;
+
+export const defaultAlertSettingsConfig = {
+ generic: {
+ authorizationKey: KEY,
+ formPath: INVALID_URL,
+ url: GENERIC_URL,
+ alertsSetupUrl: INVALID_URL,
+ alertsUsageUrl: INVALID_URL,
+ activated: ACTIVATED,
+ },
+ prometheus: {
+ authorizationKey: KEY,
+ prometheusFormPath: INVALID_URL,
+ prometheusUrl: PROMETHEUS_URL,
+ activated: ACTIVATED,
+ },
+ opsgenie: {
+ opsgenieMvcIsAvailable: true,
+ formPath: INVALID_URL,
+ activated: ACTIVATED,
+ opsgenieMvcTargetUrl: GENERIC_URL,
+ },
+};