Commit 866b1589 authored by Michael Lunøe's avatar Michael Lunøe

Merge branch '336360-upsell-the-gitlab-terraform-features' into 'master'

Upsell the GitLab Terraform features - iteration 3 frontend

See merge request gitlab-org/gitlab!68064
parents 675fa01f 5de31afb
<script> <script>
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import { setCookie } from '~/lib/utils/common_utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import { EVENT_LABEL, DISMISS_EVENT, CLICK_EVENT } from '../constants'; import { EVENT_LABEL, DISMISS_EVENT, CLICK_EVENT } from '../constants';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL }); const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
...@@ -19,24 +19,19 @@ export default { ...@@ -19,24 +19,19 @@ export default {
}, },
components: { components: {
GlBanner, GlBanner,
UserCalloutDismisser,
}, },
mixins: [trackingMixin], mixins: [trackingMixin],
inject: ['terraformImagePath', 'bannerDismissedKey'], inject: ['terraformImagePath'],
data() {
return {
isVisible: true,
};
},
computed: { computed: {
docsUrl() { docsUrl() {
return helpPagePath('user/infrastructure/terraform_state'); return helpPagePath('user/infrastructure/iac/terraform_state.md');
}, },
}, },
methods: { methods: {
handleClose() { handleClose() {
setCookie(this.bannerDismissedKey, true);
this.isVisible = false;
this.track(DISMISS_EVENT); this.track(DISMISS_EVENT);
this.$refs.calloutDismisser.dismiss();
}, },
buttonClick() { buttonClick() {
this.track(CLICK_EVENT); this.track(CLICK_EVENT);
...@@ -45,17 +40,21 @@ export default { ...@@ -45,17 +40,21 @@ export default {
}; };
</script> </script>
<template> <template>
<div v-if="isVisible" class="gl-py-5"> <user-callout-dismisser ref="calloutDismisser" feature-name="terraform_notification_dismissed">
<gl-banner <template #default="{ shouldShowCallout }">
:title="$options.i18n.title" <div v-if="shouldShowCallout" class="gl-py-5">
:button-text="$options.i18n.buttonText" <gl-banner
:button-link="docsUrl" :title="$options.i18n.title"
:svg-path="terraformImagePath" :button-text="$options.i18n.buttonText"
variant="promotion" :button-link="docsUrl"
@primary="buttonClick" :svg-path="terraformImagePath"
@close="handleClose" variant="promotion"
> @primary="buttonClick"
<p>{{ $options.i18n.description }}</p> @close="handleClose"
</gl-banner> >
</div> <p>{{ $options.i18n.description }}</p>
</gl-banner>
</div>
</template>
</user-callout-dismisser>
</template> </template>
import Vue from 'vue'; import Vue from 'vue';
import { parseBoolean, getCookie } from '~/lib/utils/common_utils'; import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import TerraformNotification from './components/terraform_notification.vue'; import TerraformNotification from './components/terraform_notification.vue';
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default () => { export default () => {
const el = document.querySelector('.js-terraform-notification'); const el = document.querySelector('.js-terraform-notification');
const bannerDismissedKey = 'terraform_notification_dismissed';
if (!el || parseBoolean(getCookie(bannerDismissedKey))) { if (!el) {
return false; return false;
} }
...@@ -14,9 +20,9 @@ export default () => { ...@@ -14,9 +20,9 @@ export default () => {
return new Vue({ return new Vue({
el, el,
apolloProvider,
provide: { provide: {
terraformImagePath, terraformImagePath,
bannerDismissedKey,
}, },
render: (createElement) => createElement(TerraformNotification), render: (createElement) => createElement(TerraformNotification),
}); });
......
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import { setCookie, parseBoolean } from '~/lib/utils/common_utils'; import { mockTracking } from 'helpers/tracking_helper';
import TerraformNotification from '~/projects/terraform_notification/components/terraform_notification.vue'; import TerraformNotification from '~/projects/terraform_notification/components/terraform_notification.vue';
import { import {
EVENT_LABEL, EVENT_LABEL,
...@@ -9,64 +9,77 @@ import { ...@@ -9,64 +9,77 @@ import {
CLICK_EVENT, CLICK_EVENT,
} from '~/projects/terraform_notification/constants'; } from '~/projects/terraform_notification/constants';
jest.mock('~/lib/utils/common_utils');
const terraformImagePath = '/path/to/image'; const terraformImagePath = '/path/to/image';
const bannerDismissedKey = 'terraform_notification_dismissed';
describe('TerraformNotificationBanner', () => { describe('TerraformNotificationBanner', () => {
let wrapper; let wrapper;
let trackingSpy; let trackingSpy;
let userCalloutDismissSpy;
const provideData = { const provideData = {
terraformImagePath, terraformImagePath,
bannerDismissedKey,
}; };
const findBanner = () => wrapper.findComponent(GlBanner); const findBanner = () => wrapper.findComponent(GlBanner);
beforeEach(() => { const createComponent = ({ shouldShowCallout = true } = {}) => {
userCalloutDismissSpy = jest.fn();
wrapper = shallowMount(TerraformNotification, { wrapper = shallowMount(TerraformNotification, {
provide: provideData, provide: provideData,
stubs: { GlBanner }, stubs: {
GlBanner,
UserCalloutDismisser: makeMockUserCalloutDismisser({
dismiss: userCalloutDismissSpy,
shouldShowCallout,
}),
},
}); });
};
beforeEach(() => {
createComponent();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
}); });
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
parseBoolean.mockReturnValue(false);
unmockTracking();
}); });
describe('when the dismiss cookie is not set', () => { describe('when user has already dismissed the banner', () => {
beforeEach(() => {
createComponent({
shouldShowCallout: false,
});
});
it('should not render the banner', () => {
expect(findBanner().exists()).toBe(false);
});
});
describe("when user hasn't yet dismissed the banner", () => {
it('should render the banner', () => { it('should render the banner', () => {
expect(findBanner().exists()).toBe(true); expect(findBanner().exists()).toBe(true);
}); });
}); });
describe('when close button is clicked', () => { describe('when close button is clicked', () => {
beforeEach(async () => { beforeEach(() => {
await findBanner().vm.$emit('close'); wrapper.vm.$refs.calloutDismisser.dismiss = userCalloutDismissSpy;
}); findBanner().vm.$emit('close');
it('should set the cookie with the bannerDismissedKey', () => {
expect(setCookie).toHaveBeenCalledWith(bannerDismissedKey, true);
}); });
it('should send the dismiss event', () => { it('should send the dismiss event', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, DISMISS_EVENT, { expect(trackingSpy).toHaveBeenCalledWith(undefined, DISMISS_EVENT, {
label: EVENT_LABEL, label: EVENT_LABEL,
}); });
}); });
it('should call the dismiss callback', () => {
it('should remove the banner', () => { expect(userCalloutDismissSpy).toHaveBeenCalledTimes(1);
expect(findBanner().exists()).toBe(false);
}); });
}); });
describe('when docs link is clicked', () => { describe('when docs link is clicked', () => {
beforeEach(async () => { beforeEach(() => {
await findBanner().vm.$emit('primary'); findBanner().vm.$emit('primary');
}); });
it('should send button click event', () => { it('should send button click event', () => {
......
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