Commit 061963f3 authored by Brandon Labuschagne's avatar Brandon Labuschagne

Merge branch 'afontaine/add-events-to-environments' into 'master'

Add Snowplow Tracking to Environment Actions

See merge request gitlab-org/gitlab!66968
parents deae8d1e 2d5dc001
...@@ -776,23 +776,39 @@ export default { ...@@ -776,23 +776,39 @@ export default {
role="gridcell" role="gridcell"
> >
<div class="btn-group table-action-buttons" role="group"> <div class="btn-group table-action-buttons" role="group">
<pin-component v-if="canShowAutoStopDate" :auto-stop-url="autoStopUrl" /> <pin-component
v-if="canShowAutoStopDate"
:auto-stop-url="autoStopUrl"
data-track-action="click_button"
data-track-label="environment_pin"
/>
<external-url-component <external-url-component
v-if="externalURL && canReadEnvironment" v-if="externalURL && canReadEnvironment"
:external-url="externalURL" :external-url="externalURL"
data-track-action="click_button"
data-track-label="environment_url"
/> />
<monitoring-button-component <monitoring-button-component
v-if="monitoringUrl && canReadEnvironment" v-if="monitoringUrl && canReadEnvironment"
:monitoring-url="monitoringUrl" :monitoring-url="monitoringUrl"
data-track-action="click_button"
data-track-label="environment_monitoring"
/> />
<actions-component v-if="actions.length > 0" :actions="actions" /> <actions-component
v-if="actions.length > 0"
:actions="actions"
data-track-action="click_dropdown"
data-track-label="environment_actions"
/>
<terminal-button-component <terminal-button-component
v-if="model && model.terminal_path" v-if="model && model.terminal_path"
:terminal-path="model.terminal_path" :terminal-path="model.terminal_path"
data-track-action="click_button"
data-track-label="environment_terminal"
/> />
<rollback-component <rollback-component
...@@ -800,11 +816,23 @@ export default { ...@@ -800,11 +816,23 @@ export default {
:environment="model" :environment="model"
:is-last-deployment="isLastDeployment" :is-last-deployment="isLastDeployment"
:retry-url="retryUrl" :retry-url="retryUrl"
data-track-action="click_button"
data-track-label="environment_rollback"
/> />
<stop-component v-if="canStopEnvironment" :environment="model" /> <stop-component
v-if="canStopEnvironment"
:environment="model"
data-track-action="click_button"
data-track-label="environment_stop"
/>
<delete-component v-if="canDeleteEnvironment" :environment="model" /> <delete-component
v-if="canDeleteEnvironment"
:environment="model"
data-track-action="click_button"
data-track-label="environment_delete"
/>
</div> </div>
</div> </div>
</div> </div>
......
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { format } from 'timeago.js'; import { format } from 'timeago.js';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import ActionsComponent from '~/environments/components/environment_actions.vue';
import DeleteComponent from '~/environments/components/environment_delete.vue'; import DeleteComponent from '~/environments/components/environment_delete.vue';
import ExternalUrlComponent from '~/environments/components/environment_external_url.vue';
import EnvironmentItem from '~/environments/components/environment_item.vue'; import EnvironmentItem from '~/environments/components/environment_item.vue';
import PinComponent from '~/environments/components/environment_pin.vue'; import PinComponent from '~/environments/components/environment_pin.vue';
import RollbackComponent from '~/environments/components/environment_rollback.vue';
import StopComponent from '~/environments/components/environment_stop.vue';
import TerminalButtonComponent from '~/environments/components/environment_terminal_button.vue';
import { differenceInMilliseconds } from '~/lib/utils/datetime_utility'; import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
import { environment, folder, tableData } from './mock_data'; import { environment, folder, tableData } from './mock_data';
describe('Environment item', () => { describe('Environment item', () => {
let wrapper; let wrapper;
let tracking;
const factory = (options = {}) => { const factory = (options = {}) => {
// This destroys any wrappers created before a nested call to factory reassigns it // This destroys any wrappers created before a nested call to factory reassigns it
...@@ -28,6 +35,12 @@ describe('Environment item', () => { ...@@ -28,6 +35,12 @@ describe('Environment item', () => {
tableData, tableData,
}, },
}); });
tracking = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
unmockTracking();
}); });
const findAutoStop = () => wrapper.find('.js-auto-stop'); const findAutoStop = () => wrapper.find('.js-auto-stop');
...@@ -62,7 +75,7 @@ describe('Environment item', () => { ...@@ -62,7 +75,7 @@ describe('Environment item', () => {
}); });
it('should not render the delete button', () => { it('should not render the delete button', () => {
expect(wrapper.find(DeleteComponent).exists()).toBe(false); expect(wrapper.findComponent(DeleteComponent).exists()).toBe(false);
}); });
describe('With user information', () => { describe('With user information', () => {
...@@ -176,12 +189,14 @@ describe('Environment item', () => { ...@@ -176,12 +189,14 @@ describe('Environment item', () => {
}); });
it('should not render the auto-stop button', () => { it('should not render the auto-stop button', () => {
expect(wrapper.find(PinComponent).exists()).toBe(false); expect(wrapper.findComponent(PinComponent).exists()).toBe(false);
}); });
}); });
describe('With auto-stop date', () => { describe('With auto-stop date', () => {
describe('in the future', () => { describe('in the future', () => {
let pin;
const futureDate = new Date(Date.now() + 100000); const futureDate = new Date(Date.now() + 100000);
beforeEach(() => { beforeEach(() => {
factory({ factory({
...@@ -195,6 +210,9 @@ describe('Environment item', () => { ...@@ -195,6 +210,9 @@ describe('Environment item', () => {
shouldShowAutoStopDate: true, shouldShowAutoStopDate: true,
}, },
}); });
tracking = mockTracking(undefined, wrapper.element, jest.spyOn);
pin = wrapper.findComponent(PinComponent);
}); });
it('renders the date', () => { it('renders the date', () => {
...@@ -202,7 +220,15 @@ describe('Environment item', () => { ...@@ -202,7 +220,15 @@ describe('Environment item', () => {
}); });
it('should render the auto-stop button', () => { it('should render the auto-stop button', () => {
expect(wrapper.find(PinComponent).exists()).toBe(true); expect(pin.exists()).toBe(true);
});
it('should tracks clicks', () => {
pin.trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_pin',
});
}); });
}); });
...@@ -227,33 +253,104 @@ describe('Environment item', () => { ...@@ -227,33 +253,104 @@ describe('Environment item', () => {
}); });
it('should not render the suto-stop button', () => { it('should not render the suto-stop button', () => {
expect(wrapper.find(PinComponent).exists()).toBe(false); expect(wrapper.findComponent(PinComponent).exists()).toBe(false);
}); });
}); });
}); });
}); });
describe('With manual actions', () => { describe('With manual actions', () => {
let actions;
beforeEach(() => {
actions = wrapper.findComponent(ActionsComponent);
});
it('should render actions component', () => { it('should render actions component', () => {
expect(wrapper.find('.js-manual-actions-container')).toBeDefined(); expect(actions.exists()).toBe(true);
});
it('should track clicks', () => {
actions.trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_dropdown', {
label: 'environment_actions',
});
}); });
}); });
describe('With external URL', () => { describe('With external URL', () => {
let externalUrl;
beforeEach(() => {
externalUrl = wrapper.findComponent(ExternalUrlComponent);
});
it('should render external url component', () => { it('should render external url component', () => {
expect(wrapper.find('.js-external-url-container')).toBeDefined(); expect(externalUrl.exists()).toBe(true);
});
it('should track clicks', () => {
externalUrl.trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_url',
});
}); });
}); });
describe('With stop action', () => { describe('With stop action', () => {
let stop;
beforeEach(() => {
stop = wrapper.findComponent(StopComponent);
});
it('should render stop action component', () => { it('should render stop action component', () => {
expect(wrapper.find('.js-stop-component-container')).toBeDefined(); expect(stop.exists()).toBe(true);
});
it('should track clicks', () => {
stop.trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_stop',
});
}); });
}); });
describe('With retry action', () => { describe('With retry action', () => {
let rollback;
beforeEach(() => {
rollback = wrapper.findComponent(RollbackComponent);
});
it('should render rollback component', () => { it('should render rollback component', () => {
expect(wrapper.find('.js-rollback-component-container')).toBeDefined(); expect(rollback.exists()).toBe(true);
});
it('should track clicks', () => {
rollback.trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_rollback',
});
});
});
describe('With terminal path', () => {
let terminal;
beforeEach(() => {
terminal = wrapper.findComponent(TerminalButtonComponent);
});
it('should render terminal action component', () => {
expect(terminal.exists()).toBe(true);
});
it('should track clicks', () => {
triggerEvent(terminal.element);
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_terminal',
});
}); });
}); });
}); });
...@@ -312,7 +409,17 @@ describe('Environment item', () => { ...@@ -312,7 +409,17 @@ describe('Environment item', () => {
}); });
it('should render the delete button', () => { it('should render the delete button', () => {
expect(wrapper.find(DeleteComponent).exists()).toBe(true); expect(wrapper.findComponent(DeleteComponent).exists()).toBe(true);
});
it('should trigger a tracking event', async () => {
tracking = mockTracking(undefined, wrapper.element, jest.spyOn);
await wrapper.findComponent(DeleteComponent).trigger('click');
expect(tracking).toHaveBeenCalledWith('_category_', 'click_button', {
label: 'environment_delete',
});
}); });
}); });
}); });
...@@ -71,6 +71,8 @@ const environment = { ...@@ -71,6 +71,8 @@ const environment = {
state: 'stopped', state: 'stopped',
external_url: 'http://external.com', external_url: 'http://external.com',
environment_type: null, environment_type: null,
can_stop: true,
terminal_path: '/terminal',
last_deployment: { last_deployment: {
id: 66, id: 66,
iid: 6, iid: 6,
......
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