Commit 25ad8786 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch 'alert-endpoint-trigger-test' into 'master'

Alert endpoint trigger test

See merge request gitlab-org/gitlab!35970
parents bc18b58b baf38c4e
...@@ -21,6 +21,7 @@ export const i18n = { ...@@ -21,6 +21,7 @@ export const i18n = {
'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.', 'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
), ),
endPointActivated: s__('AlertSettings|Alerts endpoint successfully activated.'), endPointActivated: s__('AlertSettings|Alerts endpoint successfully activated.'),
changesSaved: s__('AlertSettings|Your changes were successfully updated.'),
prometheusInfo: s__('AlertSettings|Add URL and auth key to your Prometheus config file'), prometheusInfo: s__('AlertSettings|Add URL and auth key to your Prometheus config file'),
integrationsInfo: s__( integrationsInfo: s__(
'AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}', 'AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}',
...@@ -32,10 +33,20 @@ export const i18n = { ...@@ -32,10 +33,20 @@ export const i18n = {
authKeyLabel: s__('AlertSettings|Authorization key'), authKeyLabel: s__('AlertSettings|Authorization key'),
urlLabel: s__('AlertSettings|Webhook URL'), urlLabel: s__('AlertSettings|Webhook URL'),
activeLabel: s__('AlertSettings|Active'), activeLabel: s__('AlertSettings|Active'),
apiBaseUrlHelpText: s__(' AlertSettings|URL cannot be blank and must start with http or https'), apiBaseUrlHelpText: s__('AlertSettings|URL cannot be blank and must start with http or https'),
testAlertInfo: s__('AlertSettings|Test alert payload'),
alertJson: s__('AlertSettings|Alert test payload'),
alertJsonPlaceholder: s__('AlertSettings|Enter test alert JSON....'),
testAlertFailed: s__('AlertSettings|Test failed. Do you still want to save your changes anyway?'),
testAlertSuccess: s__(
'AlertSettings|Test alert sent successfully. If you have made other changes, please save them now.',
),
authKeyRest: s__('AlertSettings|Authorization key has been successfully reset'),
}; };
export const serviceOptions = [ export const serviceOptions = [
{ value: 'generic', text: s__('AlertSettings|Generic') }, { value: 'generic', text: s__('AlertSettings|Generic') },
{ value: 'prometheus', text: s__('AlertSettings|External Prometheus') }, { value: 'prometheus', text: s__('AlertSettings|External Prometheus') },
]; ];
export const JSON_VALIDATE_DELAY = 250;
/* eslint-disable @gitlab/require-i18n-strings */
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
export default { export default {
...@@ -24,4 +25,12 @@ export default { ...@@ -24,4 +25,12 @@ export default {
}, },
}); });
}, },
updateTestAlert({ endpoint, data, authKey }) {
return axios.post(endpoint, data, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${authKey}`,
},
});
},
}; };
...@@ -17,7 +17,7 @@ module OperationsHelper ...@@ -17,7 +17,7 @@ module OperationsHelper
def alerts_settings_data def alerts_settings_data
{ {
'prometheus_activated' => prometheus_service.activated?.to_s, 'prometheus_activated' => prometheus_service.manual_configuration?.to_s,
'activated' => alerts_service.activated?.to_s, 'activated' => alerts_service.activated?.to_s,
'prometheus_form_path' => scoped_integration_path(prometheus_service), 'prometheus_form_path' => scoped_integration_path(prometheus_service),
'form_path' => scoped_integration_path(alerts_service), 'form_path' => scoped_integration_path(alerts_service),
......
...@@ -16,9 +16,6 @@ msgstr "" ...@@ -16,9 +16,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
msgid " AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
msgid " %{start} to %{end}" msgid " %{start} to %{end}"
msgstr "" msgstr ""
...@@ -2086,15 +2083,24 @@ msgstr "" ...@@ -2086,15 +2083,24 @@ msgstr ""
msgid "AlertSettings|Add URL and auth key to your Prometheus config file" msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
msgstr "" msgstr ""
msgid "AlertSettings|Alert test payload"
msgstr ""
msgid "AlertSettings|Alerts endpoint successfully activated." msgid "AlertSettings|Alerts endpoint successfully activated."
msgstr "" msgstr ""
msgid "AlertSettings|Authorization key" msgid "AlertSettings|Authorization key"
msgstr "" msgstr ""
msgid "AlertSettings|Authorization key has been successfully reset"
msgstr ""
msgid "AlertSettings|Copy" msgid "AlertSettings|Copy"
msgstr "" msgstr ""
msgid "AlertSettings|Enter test alert JSON...."
msgstr ""
msgid "AlertSettings|External Prometheus" msgid "AlertSettings|External Prometheus"
msgstr "" msgstr ""
...@@ -2119,6 +2125,15 @@ msgstr "" ...@@ -2119,6 +2125,15 @@ msgstr ""
msgid "AlertSettings|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." msgid "AlertSettings|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."
msgstr "" msgstr ""
msgid "AlertSettings|Test alert payload"
msgstr ""
msgid "AlertSettings|Test alert sent successfully. If you have made other changes, please save them now."
msgstr ""
msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?"
msgstr ""
msgid "AlertSettings|There was an error updating the the alert settings. Please refresh the page to try again." msgid "AlertSettings|There was an error updating the the alert settings. Please refresh the page to try again."
msgstr "" msgstr ""
...@@ -2128,6 +2143,9 @@ msgstr "" ...@@ -2128,6 +2143,9 @@ msgstr ""
msgid "AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again." msgid "AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again."
msgstr "" msgstr ""
msgid "AlertSettings|URL cannot be blank and must start with http or https"
msgstr ""
msgid "AlertSettings|Webhook URL" msgid "AlertSettings|Webhook URL"
msgstr "" msgstr ""
...@@ -2137,6 +2155,9 @@ msgstr "" ...@@ -2137,6 +2155,9 @@ msgstr ""
msgid "AlertSettings|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." msgid "AlertSettings|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."
msgstr "" msgstr ""
msgid "AlertSettings|Your changes were successfully updated."
msgstr ""
msgid "AlertSettings|http://prometheus.example.com/" msgid "AlertSettings|http://prometheus.example.com/"
msgstr "" msgstr ""
...@@ -19939,9 +19960,6 @@ msgstr "" ...@@ -19939,9 +19960,6 @@ msgstr ""
msgid "Save Changes" msgid "Save Changes"
msgstr "" msgstr ""
msgid "Save and test changes"
msgstr ""
msgid "Save anyway" msgid "Save anyway"
msgstr "" msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AlertsSettingsForm prometheus is active renders a valid "select" 1`] = `"<gl-form-select-stub options=\\"[object Object],[object Object]\\" data-testid=\\"alert-settings-select\\" value=\\"prometheus\\"></gl-form-select-stub>"`;
exports[`AlertsSettingsForm with default values renders the initial template 1`] = ` exports[`AlertsSettingsForm with default values renders the initial template 1`] = `
"<div> "<div>
<!----> <!---->
...@@ -20,29 +18,20 @@ exports[`AlertsSettingsForm with default values renders the initial template 1`] ...@@ -20,29 +18,20 @@ exports[`AlertsSettingsForm with default values renders the initial template 1`]
</gl-form-group-stub> </gl-form-group-stub>
<!----> <!---->
<gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\" label-class=\\"label-bold\\"> <gl-form-group-stub label=\\"Webhook URL\\" label-for=\\"url\\" label-class=\\"label-bold\\">
<div class=\\"input-group\\"> <gl-form-input-group-stub value=\\"/alerts/notify.json\\" predefinedoptions=\\"[object Object]\\" id=\\"url\\" readonly=\\"true\\"></gl-form-input-group-stub> <span class=\\"gl-text-gray-400\\">
<gl-form-input-stub id=\\"url\\" readonly=\\"true\\" value=\\"/alerts/notify.json\\"></gl-form-input-stub> <span class=\\"input-group-append\\"><clipboard-button-stub text=\\"/alerts/notify.json\\" title=\\"Copy\\" tooltipplacement=\\"top\\" cssclass=\\"btn-default\\"></clipboard-button-stub></span>
</div> <span class=\\"gl-text-gray-400\\">
</span> </span>
</gl-form-group-stub> </gl-form-group-stub>
<gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\" label-class=\\"label-bold\\"> <gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\" label-class=\\"label-bold\\">
<div class=\\"input-group\\"> <gl-form-input-group-stub value=\\"abcedfg123\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"true\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
<gl-form-input-stub id=\\"authorization-key\\" readonly=\\"true\\" value=\\"abcedfg123\\"></gl-form-input-stub> <span class=\\"input-group-append\\"><clipboard-button-stub text=\\"abcedfg123\\" title=\\"Copy\\" tooltipplacement=\\"top\\" cssclass=\\"btn-default\\"></clipboard-button-stub></span>
</div>
<gl-button-stub category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub> <gl-button-stub category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" 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\\"> <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. 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-modal-stub>
</gl-form-group-stub> </gl-form-group-stub>
<div class=\\"footer-block row-content-block gl-display-flex gl-justify-content-space-between d-none\\"> <!---->
<gl-button-stub category=\\"primary\\" variant=\\"success\\" size=\\"medium\\" icon=\\"\\" type=\\"submit\\"> <gl-button-stub category=\\"tertiary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" disabled=\\"true\\">Test alert payload</gl-button-stub>
Save and test changes <!---->
</gl-button-stub>
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" type=\\"reset\\">
Cancel
</gl-button-stub>
</div>
</gl-form-stub> </gl-form-stub>
</div>" </div>"
`; `;
...@@ -36,8 +36,12 @@ describe('AlertsSettingsForm', () => { ...@@ -36,8 +36,12 @@ describe('AlertsSettingsForm', () => {
props = defaultProps, props = defaultProps,
{ methods } = {}, { methods } = {},
alertIntegrationsDropdown = false, alertIntegrationsDropdown = false,
data,
) => { ) => {
wrapper = shallowMount(AlertsSettingsForm, { wrapper = shallowMount(AlertsSettingsForm, {
data() {
return { ...data };
},
propsData: { propsData: {
...defaultProps, ...defaultProps,
...props, ...props,
...@@ -52,6 +56,7 @@ describe('AlertsSettingsForm', () => { ...@@ -52,6 +56,7 @@ describe('AlertsSettingsForm', () => {
}; };
const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]'); const findSelect = () => wrapper.find('[data-testid="alert-settings-select"]');
const findJsonInput = () => wrapper.find('#alert-json');
const findUrl = () => wrapper.find('#url'); const findUrl = () => wrapper.find('#url');
const findAuthorizationKey = () => wrapper.find('#authorization-key'); const findAuthorizationKey = () => wrapper.find('#authorization-key');
const findApiUrl = () => wrapper.find('#api-url'); const findApiUrl = () => wrapper.find('#api-url');
...@@ -115,13 +120,13 @@ describe('AlertsSettingsForm', () => { ...@@ -115,13 +120,13 @@ describe('AlertsSettingsForm', () => {
describe('activate toggle', () => { describe('activate toggle', () => {
it('triggers toggleActivated method', () => { it('triggers toggleActivated method', () => {
const toggleActivated = jest.fn(); const toggleService = jest.fn();
const methods = { toggleActivated }; const methods = { toggleService };
createComponent(defaultProps, { methods }); createComponent(defaultProps, { methods });
wrapper.find(ToggleButton).vm.$emit('change', true); wrapper.find(ToggleButton).vm.$emit('change', true);
expect(toggleActivated).toHaveBeenCalled(); expect(toggleService).toHaveBeenCalled();
}); });
describe('error is encountered', () => { describe('error is encountered', () => {
...@@ -149,7 +154,7 @@ describe('AlertsSettingsForm', () => { ...@@ -149,7 +154,7 @@ describe('AlertsSettingsForm', () => {
}); });
it('renders a valid "select"', () => { it('renders a valid "select"', () => {
expect(findSelect().html()).toMatchSnapshot(); expect(findSelect().exists()).toBe(true);
}); });
it('shows the API URL input', () => { it('shows the API URL input', () => {
...@@ -160,9 +165,53 @@ describe('AlertsSettingsForm', () => { ...@@ -160,9 +165,53 @@ describe('AlertsSettingsForm', () => {
expect(findUrl().exists()).toBe(true); expect(findUrl().exists()).toBe(true);
expect(findUrl().attributes('value')).toBe(PROMETHEUS_URL); expect(findUrl().attributes('value')).toBe(PROMETHEUS_URL);
}); });
});
describe('trigger test alert', () => {
beforeEach(() => {
createComponent({ generic: { ...defaultProps.generic, initialActivated: true } }, {}, true);
});
it('should enable the JSON input', () => {
expect(findJsonInput().exists()).toBe(true);
expect(findJsonInput().props('value')).toBe(null);
});
it('should validate JSON input', () => {
createComponent({ generic: { ...defaultProps.generic } }, {}, true, {
testAlertJson: '{ "value": "test" }',
});
findJsonInput().vm.$emit('change');
return wrapper.vm.$nextTick().then(() => {
expect(findJsonInput().attributes('state')).toBe('true');
});
});
describe('alert service is toggled', () => {
it('should show a info alert if successful', () => {
const formPath = 'some/path';
const toggleService = true;
mockAxios.onPut(formPath).replyOnce(200);
createComponent({ generic: { ...defaultProps.generic, formPath } });
return wrapper.vm.toggleGenericActivated(toggleService).then(() => {
expect(wrapper.find(GlAlert).attributes('variant')).toBe('info');
});
});
it('should not show a footer block', () => { it('should show a error alert if failed', () => {
expect(wrapper.find('.footer-block').classes('d-none')).toBe(true); const formPath = 'some/path';
const toggleService = true;
mockAxios.onPut(formPath).replyOnce(404);
createComponent({ generic: { ...defaultProps.generic, formPath } });
return wrapper.vm.toggleGenericActivated(toggleService).then(() => {
expect(wrapper.find(GlAlert).attributes('variant')).toBe('danger');
});
});
}); });
}); });
}); });
...@@ -45,7 +45,9 @@ RSpec.describe OperationsHelper do ...@@ -45,7 +45,9 @@ RSpec.describe OperationsHelper do
end end
context 'with external Prometheus configured' do context 'with external Prometheus configured' do
let_it_be(:prometheus_service, reload: true) { create(:prometheus_service, project: project) } let_it_be(:prometheus_service, reload: true) do
create(:prometheus_service, project: project)
end
context 'with external Prometheus enabled' do context 'with external Prometheus enabled' do
it 'returns the correct values' do it 'returns the correct values' do
...@@ -57,11 +59,7 @@ RSpec.describe OperationsHelper do ...@@ -57,11 +59,7 @@ RSpec.describe OperationsHelper do
end end
context 'with external Prometheus disabled' do context 'with external Prometheus disabled' do
before do shared_examples 'Prometheus is disabled' do
# Prometheus services uses manual_configuration as an alias for active, beware
prometheus_service.update!(manual_configuration: false)
end
it 'returns the correct values' do it 'returns the correct values' do
expect(subject).to include( expect(subject).to include(
'prometheus_activated' => 'false', 'prometheus_activated' => 'false',
...@@ -70,6 +68,25 @@ RSpec.describe OperationsHelper do ...@@ -70,6 +68,25 @@ RSpec.describe OperationsHelper do
end end
end end
let(:cluster_managed) { false }
before do
allow(prometheus_service)
.to receive(:prometheus_available?)
.and_return(cluster_managed)
prometheus_service.update!(manual_configuration: false)
end
include_examples 'Prometheus is disabled'
context 'when cluster managed' do
let(:cluster_managed) { true }
include_examples 'Prometheus is disabled'
end
end
context 'with project alert setting' do context 'with project alert setting' do
let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) } let_it_be(:project_alerting_setting) { create(:project_alerting_setting, project: project) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment