Commit 28499b1e authored by Alex Buijs's avatar Alex Buijs

Apply reviewer feedback

- Convert CTA button to link
- Add translation scope
- Set a cookie when clicking the CTA
- Increase cookie expiration in tests
- Add empty value for img tag alt attr
- Change copy
- Flip colored border of dark popover
- Remove popover offset
parent 75922d85
<script> <script>
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import { I18N } from '../constants'; import { I18N } from '../constants';
import { isDismissed, dismiss, trackShow, trackCtaClicked } from '../utils'; import { isDismissed, dismiss, trackShow, trackCtaClicked, trackDismissed } from '../utils';
export default { export default {
components: { components: {
...@@ -27,8 +27,10 @@ export default { ...@@ -27,8 +27,10 @@ export default {
onDismiss() { onDismiss() {
this.isVisible = false; this.isVisible = false;
dismiss(); dismiss();
trackDismissed();
}, },
onClick() { onClick() {
dismiss();
trackCtaClicked(); trackCtaClicked();
}, },
}, },
......
<script> <script>
import { GlPopover, GlButton } from '@gitlab/ui'; import { GlPopover, GlButton, GlLink } from '@gitlab/ui';
import { I18N, POPOVER_TARGET } from '../constants'; import { I18N, POPOVER_TARGET } from '../constants';
import { isDismissed, dismiss, trackShow, trackCtaClicked } from '../utils'; import { isDismissed, dismiss, trackShow, trackCtaClicked, trackDismissed } from '../utils';
export default { export default {
components: { components: {
GlPopover, GlPopover,
GlButton, GlButton,
GlLink,
}, },
props: { props: {
sastDocumentationPath: { sastDocumentationPath: {
...@@ -29,8 +30,10 @@ export default { ...@@ -29,8 +30,10 @@ export default {
onDismiss() { onDismiss() {
this.isVisible = false; this.isVisible = false;
dismiss(); dismiss();
trackDismissed();
}, },
onClick() { onClick() {
dismiss();
trackCtaClicked(); trackCtaClicked();
}, },
}, },
...@@ -46,11 +49,10 @@ export default { ...@@ -46,11 +49,10 @@ export default {
show show
triggers="manual" triggers="manual"
placement="bottomright" placement="bottomright"
offset="93" :css-classes="['marketing-popover', 'gl-border-4']"
:css-classes="['marketing-popover', 'gl-border-4', 'gl-border-t-solid']"
> >
<div class="gl-display-flex gl-mt-n2"> <div class="gl-display-flex gl-mt-n2">
<img :src="$options.gitlabLogo" height="24" width="24" class="gl-ml-2 gl-mr-3" /> <img :src="$options.gitlabLogo" :alt="''" height="24" width="24" class="gl-ml-2 gl-mr-3" />
<div> <div>
<div <div
class="gl-font-weight-bold gl-font-lg gl-line-height-20 gl-text-theme-indigo-900 gl-mb-3" class="gl-font-weight-bold gl-font-lg gl-line-height-20 gl-text-theme-indigo-900 gl-mb-3"
...@@ -60,15 +62,14 @@ export default { ...@@ -60,15 +62,14 @@ export default {
<div class="gl-font-base gl-line-height-20 gl-mb-3"> <div class="gl-font-base gl-line-height-20 gl-mb-3">
{{ $options.i18n.bodyText }} {{ $options.i18n.bodyText }}
</div> </div>
<gl-button variant="link" :href="sastDocumentationPath" @click="onClick"> <gl-link :href="sastDocumentationPath" @click="onClick">
{{ $options.i18n.linkText }} {{ $options.i18n.linkText }}
</gl-button> </gl-link>
</div> </div>
<gl-button <gl-button
category="tertiary" category="tertiary"
class="gl-align-self-start gl-mt-n3 gl-mr-n3" class="gl-align-self-start gl-mt-n3 gl-mr-n3"
icon="close" icon="close"
data-testid="close-btn"
:aria-label="__('Close')" :aria-label="__('Close')"
@click="onDismiss" @click="onDismiss"
/> />
......
<script> <script>
import { GlPopover, GlButton } from '@gitlab/ui'; import { GlPopover, GlButton, GlLink } from '@gitlab/ui';
import { I18N, POPOVER_TARGET } from '../constants'; import { I18N, POPOVER_TARGET } from '../constants';
import { isDismissed, dismiss, trackShow, trackCtaClicked } from '../utils'; import { isDismissed, dismiss, trackShow, trackCtaClicked, trackDismissed } from '../utils';
export default { export default {
components: { components: {
GlPopover, GlPopover,
GlButton, GlButton,
GlLink,
}, },
props: { props: {
sastDocumentationPath: { sastDocumentationPath: {
...@@ -29,8 +30,10 @@ export default { ...@@ -29,8 +30,10 @@ export default {
onDismiss() { onDismiss() {
this.isVisible = false; this.isVisible = false;
dismiss(); dismiss();
trackDismissed();
}, },
onClick() { onClick() {
dismiss();
trackCtaClicked(); trackCtaClicked();
}, },
}, },
...@@ -39,14 +42,7 @@ export default { ...@@ -39,14 +42,7 @@ export default {
</script> </script>
<template> <template>
<gl-popover <gl-popover v-if="isVisible" :target="target" show triggers="manual" placement="bottomright">
v-if="isVisible"
:target="target"
show
triggers="manual"
placement="bottomright"
offset="53"
>
<template #title> <template #title>
<div class="gl-display-flex"> <div class="gl-display-flex">
<span> <span>
...@@ -57,7 +53,6 @@ export default { ...@@ -57,7 +53,6 @@ export default {
category="tertiary" category="tertiary"
class="gl-align-self-start close gl-opacity-10" class="gl-align-self-start close gl-opacity-10"
icon="close" icon="close"
data-testid="close-btn"
:aria-label="__('Close')" :aria-label="__('Close')"
@click="onDismiss" @click="onDismiss"
/> />
...@@ -65,9 +60,9 @@ export default { ...@@ -65,9 +60,9 @@ export default {
</template> </template>
{{ $options.i18n.bodyText }} {{ $options.i18n.bodyText }}
<div class="gl-text-right gl-font-weight-bold"> <div class="gl-text-right gl-font-weight-bold">
<gl-button variant="link" :href="sastDocumentationPath" @click="onClick"> <gl-link :href="sastDocumentationPath" @click="onClick">
{{ $options.i18n.linkText }} {{ $options.i18n.linkText }}
</gl-button> </gl-link>
</div> </div>
</gl-popover> </gl-popover>
</template> </template>
...@@ -11,6 +11,6 @@ export const I18N = { ...@@ -11,6 +11,6 @@ export const I18N = {
bodyText: s__( bodyText: s__(
'SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more.', 'SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more.',
), ),
buttonText: s__('SastEntryPoints|Learn more'), buttonText: s__('SastEntryPoints|Learn more.'),
linkText: s__('SastEntryPoints|How do I set up SAST?'), linkText: s__('SastEntryPoints|How do I set up SAST?'),
}; };
...@@ -10,6 +10,9 @@ export const isDismissed = () => { ...@@ -10,6 +10,9 @@ export const isDismissed = () => {
export const dismiss = () => { export const dismiss = () => {
setCookie(COOKIE_NAME, 'true'); setCookie(COOKIE_NAME, 'true');
};
export const trackDismissed = () => {
tracking.event('dismissed'); tracking.event('dismissed');
}; };
......
...@@ -2,13 +2,32 @@ ...@@ -2,13 +2,32 @@
.marketing-popover { .marketing-popover {
max-width: $grid-size * 45; max-width: $grid-size * 45;
border-top-color: $theme-indigo-900;
.arrow { &.bs-popover-bottom {
@include gl-mt-n2; @include gl-border-t-solid;
&::after { border-top-color: $theme-indigo-900;
border-bottom-color: $theme-indigo-900;
.arrow {
@include gl-mt-n2;
&::after {
border-bottom-color: $theme-indigo-900;
}
}
}
&.bs-popover-top {
@include gl-border-b-solid;
border-bottom-color: $theme-indigo-900;
.arrow {
margin-bottom: -$gl-spacing-scale-2;
&::after {
border-top-color: $theme-indigo-900;
}
} }
} }
} }
...@@ -24,7 +24,7 @@ module EE ...@@ -24,7 +24,7 @@ module EE
::ProjectPresenter::AnchorData.new( ::ProjectPresenter::AnchorData.new(
false, false,
statistic_icon + _('Add Security Testing'), statistic_icon + s_('SastEntryPoints|Add Security Testing'),
help_page_path('user/application_security/sast/index'), help_page_path('user/application_security/sast/index'),
'btn-dashed js-sast-entry-point', 'btn-dashed js-sast-entry-point',
nil, nil,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
exports[`When the cookie is not set matches the snapshot 1`] = ` exports[`When the cookie is not set matches the snapshot 1`] = `
<gl-banner-stub <gl-banner-stub
buttonlink="sast_documentation_path" buttonlink="sast_documentation_path"
buttontext="Learn more" buttontext="Learn more."
class="gl-my-5" class="gl-my-5"
title="Catch your security vulnerabilities ahead of time!" title="Catch your security vulnerabilities ahead of time!"
variant="promotion" variant="promotion"
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`When the cookie is not set matches the snapshot 1`] = ` exports[`When the cookie is not set matches the snapshot 1`] = `
<div <gl-popover-stub
class="gl-popover" cssclasses="marketing-popover,gl-border-4"
offset="93" placement="bottomright"
show="" show=""
triggers="manual"
> >
<div <div
class="gl-display-flex gl-mt-n2" class="gl-display-flex gl-mt-n2"
> >
<img <img
alt=""
class="gl-ml-2 gl-mr-3" class="gl-ml-2 gl-mr-3"
height="24" height="24"
width="24" width="24"
...@@ -32,45 +34,24 @@ exports[`When the cookie is not set matches the snapshot 1`] = ` ...@@ -32,45 +34,24 @@ exports[`When the cookie is not set matches the snapshot 1`] = `
</div> </div>
<a <gl-link-stub
class="btn btn-link btn-md gl-button"
href="sast_documentation_path" href="sast_documentation_path"
> >
<!---->
<!---->
<span
class="gl-button-text"
>
How do I set up SAST? How do I set up SAST?
</span> </gl-link-stub>
</a>
</div> </div>
<button <gl-button-stub
aria-label="Close" aria-label="Close"
class="btn gl-align-self-start gl-mt-n3 gl-mr-n3 btn-default btn-md gl-button btn-default-tertiary btn-icon" buttontextclasses=""
data-testid="close-btn" category="tertiary"
type="button" class="gl-align-self-start gl-mt-n3 gl-mr-n3"
> icon="close"
<!----> size="medium"
variant="default"
<svg />
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="close-icon"
role="img"
>
<use
href="#close"
/>
</svg>
<!---->
</button>
</div> </div>
</div> </gl-popover-stub>
`; `;
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
exports[`When the cookie is not set matches the snapshot 1`] = ` exports[`When the cookie is not set matches the snapshot 1`] = `
<div <div
class="gl-popover" class="gl-popover"
offset="53"
show="" show=""
> >
...@@ -13,20 +12,12 @@ exports[`When the cookie is not set matches the snapshot 1`] = ` ...@@ -13,20 +12,12 @@ exports[`When the cookie is not set matches the snapshot 1`] = `
class="gl-text-right gl-font-weight-bold" class="gl-text-right gl-font-weight-bold"
> >
<a <a
class="btn btn-link btn-md gl-button" class="gl-link"
href="sast_documentation_path" href="sast_documentation_path"
> >
<!---->
<!---->
<span
class="gl-button-text"
>
How do I set up SAST? How do I set up SAST?
</span>
</a> </a>
</div> </div>
<div <div
...@@ -45,7 +36,6 @@ exports[`When the cookie is not set matches the snapshot 1`] = ` ...@@ -45,7 +36,6 @@ exports[`When the cookie is not set matches the snapshot 1`] = `
<button <button
aria-label="Close" aria-label="Close"
class="btn gl-align-self-start close gl-opacity-10 btn-default btn-md gl-button btn-default-tertiary btn-icon" class="btn gl-align-self-start close gl-opacity-10 btn-default btn-md gl-button btn-default-tertiary btn-icon"
data-testid="close-btn"
type="button" type="button"
> >
<!----> <!---->
......
...@@ -25,7 +25,7 @@ afterEach(() => { ...@@ -25,7 +25,7 @@ afterEach(() => {
describe('When the cookie is set', () => { describe('When the cookie is set', () => {
beforeEach(() => { beforeEach(() => {
Cookies.set(COOKIE_NAME, 'true'); Cookies.set(COOKIE_NAME, 'true', { expires: 365 });
createComponent(); createComponent();
}); });
...@@ -63,6 +63,10 @@ describe('When the cookie is not set', () => { ...@@ -63,6 +63,10 @@ describe('When the cookie is not set', () => {
it('tracks the cta_clicked event', () => { it('tracks the cta_clicked event', () => {
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked'); expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked');
}); });
it('sets a cookie', () => {
expect(Cookies.get(COOKIE_NAME)).toBe('true');
});
}); });
describe('When dismissing the component', () => { describe('When dismissing the component', () => {
......
import '~/commons'; import '~/commons';
import { GlPopover, GlButton } from '@gitlab/ui'; import { GlPopover, GlButton, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import PopoverDark from 'ee/projects/sast_entry_points_experiment/components/popover_dark.vue'; import PopoverDark from 'ee/projects/sast_entry_points_experiment/components/popover_dark.vue';
import { COOKIE_NAME } from 'ee/projects/sast_entry_points_experiment/constants'; import { COOKIE_NAME } from 'ee/projects/sast_entry_points_experiment/constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ExperimentTracking from '~/experimentation/experiment_tracking'; import ExperimentTracking from '~/experimentation/experiment_tracking';
jest.mock('~/experimentation/experiment_tracking'); jest.mock('~/experimentation/experiment_tracking');
...@@ -12,11 +12,11 @@ let wrapper; ...@@ -12,11 +12,11 @@ let wrapper;
const sastDocumentationPath = 'sast_documentation_path'; const sastDocumentationPath = 'sast_documentation_path';
const findPopover = () => wrapper.findComponent(GlPopover); const findPopover = () => wrapper.findComponent(GlPopover);
const findCtaButton = () => findPopover().findComponent(GlButton); const findCtaLink = () => findPopover().findComponent(GlLink);
const findCloseButton = () => wrapper.findByTestId('close-btn'); const findCloseButton = () => findPopover().findComponent(GlButton);
function createComponent() { function createComponent() {
wrapper = mountExtended(PopoverDark, { wrapper = shallowMount(PopoverDark, {
propsData: { sastDocumentationPath }, propsData: { sastDocumentationPath },
}); });
} }
...@@ -28,7 +28,7 @@ afterEach(() => { ...@@ -28,7 +28,7 @@ afterEach(() => {
describe('When the cookie is set', () => { describe('When the cookie is set', () => {
beforeEach(() => { beforeEach(() => {
Cookies.set(COOKIE_NAME, 'true'); Cookies.set(COOKIE_NAME, 'true', { expires: 365 });
createComponent(); createComponent();
}); });
...@@ -51,7 +51,7 @@ describe('When the cookie is not set', () => { ...@@ -51,7 +51,7 @@ describe('When the cookie is not set', () => {
}); });
it('uses the sastDocumentationPath from the props for the button link', () => { it('uses the sastDocumentationPath from the props for the button link', () => {
expect(findCtaButton().attributes('href')).toBe(sastDocumentationPath); expect(findCtaLink().attributes('href')).toBe(sastDocumentationPath);
}); });
it('matches the snapshot', () => { it('matches the snapshot', () => {
...@@ -60,12 +60,16 @@ describe('When the cookie is not set', () => { ...@@ -60,12 +60,16 @@ describe('When the cookie is not set', () => {
describe('When clicking the CTA button', () => { describe('When clicking the CTA button', () => {
beforeEach(() => { beforeEach(() => {
findCtaButton().vm.$emit('click'); findCtaLink().vm.$emit('click');
}); });
it('tracks the cta_clicked event', () => { it('tracks the cta_clicked event', () => {
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked'); expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked');
}); });
it('sets a cookie', () => {
expect(Cookies.get(COOKIE_NAME)).toBe('true');
});
}); });
describe('When dismissing the component', () => { describe('When dismissing the component', () => {
......
import '~/commons'; import '~/commons';
import { GlPopover, GlButton } from '@gitlab/ui'; import { GlPopover, GlButton, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import PopoverLight from 'ee/projects/sast_entry_points_experiment/components/popover_light.vue'; import PopoverLight from 'ee/projects/sast_entry_points_experiment/components/popover_light.vue';
import { COOKIE_NAME } from 'ee/projects/sast_entry_points_experiment/constants'; import { COOKIE_NAME } from 'ee/projects/sast_entry_points_experiment/constants';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ExperimentTracking from '~/experimentation/experiment_tracking'; import ExperimentTracking from '~/experimentation/experiment_tracking';
jest.mock('~/experimentation/experiment_tracking'); jest.mock('~/experimentation/experiment_tracking');
...@@ -12,11 +12,11 @@ let wrapper; ...@@ -12,11 +12,11 @@ let wrapper;
const sastDocumentationPath = 'sast_documentation_path'; const sastDocumentationPath = 'sast_documentation_path';
const findPopover = () => wrapper.findComponent(GlPopover); const findPopover = () => wrapper.findComponent(GlPopover);
const findCtaButton = () => findPopover().findComponent(GlButton); const findCtaLink = () => findPopover().findComponent(GlLink);
const findCloseButton = () => wrapper.findByTestId('close-btn'); const findCloseButton = () => findPopover().findComponent(GlButton);
function createComponent() { function createComponent() {
wrapper = mountExtended(PopoverLight, { wrapper = mount(PopoverLight, {
propsData: { sastDocumentationPath }, propsData: { sastDocumentationPath },
}); });
} }
...@@ -28,7 +28,7 @@ afterEach(() => { ...@@ -28,7 +28,7 @@ afterEach(() => {
describe('When the cookie is set', () => { describe('When the cookie is set', () => {
beforeEach(() => { beforeEach(() => {
Cookies.set(COOKIE_NAME, 'true'); Cookies.set(COOKIE_NAME, 'true', { expires: 365 });
createComponent(); createComponent();
}); });
...@@ -51,7 +51,7 @@ describe('When the cookie is not set', () => { ...@@ -51,7 +51,7 @@ describe('When the cookie is not set', () => {
}); });
it('uses the sastDocumentationPath from the props for the button link', () => { it('uses the sastDocumentationPath from the props for the button link', () => {
expect(findCtaButton().attributes('href')).toBe(sastDocumentationPath); expect(findCtaLink().attributes('href')).toBe(sastDocumentationPath);
}); });
it('matches the snapshot', () => { it('matches the snapshot', () => {
...@@ -60,12 +60,16 @@ describe('When the cookie is not set', () => { ...@@ -60,12 +60,16 @@ describe('When the cookie is not set', () => {
describe('When clicking the CTA button', () => { describe('When clicking the CTA button', () => {
beforeEach(() => { beforeEach(() => {
findCtaButton().vm.$emit('click'); findCtaLink().vm.$emit('click');
}); });
it('tracks the cta_clicked event', () => { it('tracks the cta_clicked event', () => {
expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked'); expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith('cta_clicked');
}); });
it('sets a cookie', () => {
expect(Cookies.get(COOKIE_NAME)).toBe('true');
});
}); });
describe('When dismissing the component', () => { describe('When dismissing the component', () => {
......
...@@ -1903,9 +1903,6 @@ msgstr "" ...@@ -1903,9 +1903,6 @@ msgstr ""
msgid "Add README" msgid "Add README"
msgstr "" msgstr ""
msgid "Add Security Testing"
msgstr ""
msgid "Add Zoom meeting" msgid "Add Zoom meeting"
msgstr "" msgstr ""
...@@ -28546,6 +28543,9 @@ msgstr "" ...@@ -28546,6 +28543,9 @@ msgstr ""
msgid "SVG illustration" msgid "SVG illustration"
msgstr "" msgstr ""
msgid "SastEntryPoints|Add Security Testing"
msgstr ""
msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!" msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
msgstr "" msgstr ""
...@@ -28555,7 +28555,7 @@ msgstr "" ...@@ -28555,7 +28555,7 @@ msgstr ""
msgid "SastEntryPoints|How do I set up SAST?" msgid "SastEntryPoints|How do I set up SAST?"
msgstr "" msgstr ""
msgid "SastEntryPoints|Learn more" msgid "SastEntryPoints|Learn more."
msgstr "" msgstr ""
msgid "Satisfied" msgid "Satisfied"
......
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