Commit 1e32cb57 authored by Enrique Alcántara's avatar Enrique Alcántara

Merge branch...

Merge branch '239468-allow-non-auto-devops-users-to-dismiss-alert-in-security-configuration-page' into 'master'

Make Auto DevOps alert dismissible in Security Configuration page

See merge request gitlab-org/gitlab!40375
parents 3071b71a 6aeaaee6
<script> <script>
import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui'; import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AutoFixSettings from './auto_fix_settings.vue'; import AutoFixSettings from './auto_fix_settings.vue';
import ManageFeature from './manage_feature.vue'; import ManageFeature from './manage_feature.vue';
...@@ -12,6 +14,7 @@ export default { ...@@ -12,6 +14,7 @@ export default {
GlSprintf, GlSprintf,
GlTable, GlTable,
AutoFixSettings, AutoFixSettings,
LocalStorageSync,
ManageFeature, ManageFeature,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
...@@ -63,6 +66,9 @@ export default { ...@@ -63,6 +66,9 @@ export default {
required: true, required: true,
}, },
}, },
data: () => ({
autoDevopsAlertDismissed: 'false',
}),
computed: { computed: {
devopsMessage() { devopsMessage() {
return this.autoDevopsEnabled return this.autoDevopsEnabled
...@@ -100,7 +106,12 @@ export default { ...@@ -100,7 +106,12 @@ export default {
]; ];
}, },
shouldShowAutoDevopsAlert() { shouldShowAutoDevopsAlert() {
return Boolean(!this.autoDevopsEnabled && !this.gitlabCiPresent && this.canEnableAutoDevops); return Boolean(
!parseBoolean(this.autoDevopsAlertDismissed) &&
!this.autoDevopsEnabled &&
!this.gitlabCiPresent &&
this.canEnableAutoDevops,
);
}, },
}, },
methods: { methods: {
...@@ -113,10 +124,14 @@ export default { ...@@ -113,10 +124,14 @@ export default {
return s__('SecurityConfiguration|Not enabled'); return s__('SecurityConfiguration|Not enabled');
}, },
dismissAutoDevopsAlert() {
this.autoDevopsAlertDismissed = 'true';
},
}, },
autoDevopsAlertMessage: s__(` autoDevopsAlertMessage: s__(`
SecurityConfiguration|You can quickly enable all security scanning tools by SecurityConfiguration|You can quickly enable all security scanning tools by
enabling %{linkStart}Auto DevOps%{linkEnd}.`), enabling %{linkStart}Auto DevOps%{linkEnd}.`),
autoDevopsAlertStorageKey: 'security_configuration_auto_devops_dismissed',
}; };
</script> </script>
...@@ -134,13 +149,18 @@ export default { ...@@ -134,13 +149,18 @@ export default {
</p> </p>
</header> </header>
<local-storage-sync
v-model="autoDevopsAlertDismissed"
:storage-key="$options.autoDevopsAlertStorageKey"
/>
<gl-alert <gl-alert
v-if="shouldShowAutoDevopsAlert" v-if="shouldShowAutoDevopsAlert"
:title="__('Auto DevOps')" :title="__('Auto DevOps')"
:primary-button-text="__('Enable Auto DevOps')" :primary-button-text="__('Enable Auto DevOps')"
:primary-button-link="autoDevopsPath" :primary-button-link="autoDevopsPath"
:dismissible="false"
class="gl-mb-5" class="gl-mb-5"
@dismiss="dismissAutoDevopsAlert"
> >
<gl-sprintf :message="$options.autoDevopsAlertMessage"> <gl-sprintf :message="$options.autoDevopsAlertMessage">
<template #link="{ content }"> <template #link="{ content }">
......
---
title: Make Auto DevOps alert in Security Configuration dismissible
merge_request: 40375
author:
type: added
...@@ -4,6 +4,8 @@ import { GlAlert, GlLink } from '@gitlab/ui'; ...@@ -4,6 +4,8 @@ import { GlAlert, GlLink } from '@gitlab/ui';
import SecurityConfigurationApp from 'ee/security_configuration/components/app.vue'; import SecurityConfigurationApp from 'ee/security_configuration/components/app.vue';
import ManageFeature from 'ee/security_configuration/components/manage_feature.vue'; import ManageFeature from 'ee/security_configuration/components/manage_feature.vue';
import stubChildren from 'helpers/stub_children'; import stubChildren from 'helpers/stub_children';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { generateFeatures } from './helpers'; import { generateFeatures } from './helpers';
const propsData = { const propsData = {
...@@ -38,6 +40,10 @@ describe('Security Configuration App', () => { ...@@ -38,6 +40,10 @@ describe('Security Configuration App', () => {
); );
}; };
beforeEach(() => {
localStorage.clear();
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
...@@ -70,21 +76,29 @@ describe('Security Configuration App', () => { ...@@ -70,21 +76,29 @@ describe('Security Configuration App', () => {
describe('Auto DevOps alert', () => { describe('Auto DevOps alert', () => {
describe.each` describe.each`
gitlabCiPresent | autoDevopsEnabled | canEnableAutoDevops | shouldShowAlert gitlabCiPresent | autoDevopsEnabled | canEnableAutoDevops | dismissed | shouldShowAlert
${false} | ${false} | ${true} | ${true} ${false} | ${false} | ${true} | ${false} | ${true}
${true} | ${false} | ${true} | ${false} ${false} | ${false} | ${true} | ${true} | ${false}
${false} | ${true} | ${true} | ${false} ${true} | ${false} | ${true} | ${false} | ${false}
${false} | ${false} | ${false} | ${false} ${false} | ${true} | ${true} | ${false} | ${false}
${false} | ${false} | ${false} | ${false} | ${false}
`( `(
'given gitlabCiPresent is $gitlabCiPresent, autoDevopsEnabled is $autoDevopsEnabled, canEnableAutoDevops is $canEnableAutoDevops', 'given gitlabCiPresent is $gitlabCiPresent, autoDevopsEnabled is $autoDevopsEnabled, dismissed is $dismissed, canEnableAutoDevops is $canEnableAutoDevops',
({ gitlabCiPresent, autoDevopsEnabled, canEnableAutoDevops, shouldShowAlert }) => { ({ gitlabCiPresent, autoDevopsEnabled, canEnableAutoDevops, dismissed, shouldShowAlert }) => {
beforeEach(() => { beforeEach(() => {
if (dismissed) {
localStorage.setItem(SecurityConfigurationApp.autoDevopsAlertStorageKey, 'true');
}
createComponent({ createComponent({
propsData: { propsData: {
gitlabCiPresent, gitlabCiPresent,
autoDevopsEnabled, autoDevopsEnabled,
canEnableAutoDevops, canEnableAutoDevops,
}, },
stubs: {
LocalStorageSync,
},
}); });
}); });
...@@ -109,12 +123,40 @@ describe('Security Configuration App', () => { ...@@ -109,12 +123,40 @@ describe('Security Configuration App', () => {
title: 'Auto DevOps', title: 'Auto DevOps',
primaryButtonText: 'Enable Auto DevOps', primaryButtonText: 'Enable Auto DevOps',
primaryButtonLink: propsData.autoDevopsPath, primaryButtonLink: propsData.autoDevopsPath,
dismissible: false,
}); });
}); });
} }
}, },
); );
describe('dismissing the alert', () => {
useLocalStorageSpy();
beforeEach(() => {
createComponent({
propsData: {
gitlabCiPresent: false,
autoDevopsEnabled: false,
canEnableAutoDevops: true,
},
stubs: {
LocalStorageSync,
},
});
getAlert().vm.$emit('dismiss');
});
it('hides the alert', () => {
expect(getAlert().exists()).toBe(false);
});
it('saves dismissal in localStorage', () => {
expect(localStorage.setItem.mock.calls).toEqual([
[SecurityConfigurationApp.autoDevopsAlertStorageKey, 'true'],
]);
});
});
}); });
describe('features table', () => { describe('features table', () => {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
const useLocalStorage = fn => { const useLocalStorage = fn => {
const origLocalStorage = window.localStorage; const origLocalStorage = window.localStorage;
let currentLocalStorage; let currentLocalStorage = origLocalStorage;
Object.defineProperty(window, 'localStorage', { Object.defineProperty(window, 'localStorage', {
get: () => currentLocalStorage, get: () => currentLocalStorage,
......
import { useLocalStorageSpy } from './local_storage_helper'; import { useLocalStorageSpy } from './local_storage_helper';
useLocalStorageSpy(); describe('block before helper is installed', () => {
it('should leave original localStorage intact', () => {
expect(localStorage.getItem).toEqual(expect.any(Function));
expect(jest.isMockFunction(localStorage.getItem)).toBe(false);
});
});
describe('localStorage helper', () => { describe('localStorage helper', () => {
useLocalStorageSpy();
it('mocks localStorage but works exactly like original localStorage', () => { it('mocks localStorage but works exactly like original localStorage', () => {
localStorage.setItem('test', 'testing'); localStorage.setItem('test', 'testing');
localStorage.setItem('test2', 'testing'); localStorage.setItem('test2', 'testing');
......
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