Commit c17100cf authored by Phil Hughes's avatar Phil Hughes

Merge branch '33751-track-usage-and-adoption-of-conan-repository' into 'master'

Add UI events tracking to Conan adoption

See merge request gitlab-org/gitlab!21908
parents 9e71803b 51b98110
......@@ -9,6 +9,7 @@ import {
GlTable,
} from '@gitlab/ui';
import _ from 'underscore';
import Tracking from '~/tracking';
import PackageInformation from './information.vue';
import NpmInstallation from './npm_installation.vue';
import MavenInstallation from './maven_installation.vue';
......@@ -17,7 +18,8 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { generatePackageInfo } from '../utils';
import { __, s__, sprintf } from '~/locale';
import { PackageType } from '../constants';
import { PackageType, TrackingActions } from '../../shared/constants';
import { packageTypeToTrackCategory } from '../../shared/utils';
export default {
name: 'PackagesApp',
......@@ -36,7 +38,8 @@ export default {
GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
},
mixins: [timeagoMixin],
mixins: [timeagoMixin, Tracking.mixin()],
trackingActions: { ...TrackingActions },
props: {
packageEntity: {
type: Object,
......@@ -145,6 +148,11 @@ export default {
created: x.created_at,
}));
},
tracking() {
return {
category: packageTypeToTrackCategory(this.packageEntity.package_type),
};
},
},
methods: {
formatSize(size) {
......@@ -233,9 +241,13 @@ export default {
>
<template #name="items">
<icon name="doc-code" class="space-right" />
<gl-link :href="items.item.downloadPath" class="js-file-download">{{
items.item.name
}}</gl-link>
<gl-link
:href="items.item.downloadPath"
class="js-file-download"
@click="track($options.trackingActions.PULL_PACKAGE)"
>
{{ items.item.name }}
</gl-link>
</template>
<template #created="items">
......@@ -253,10 +265,12 @@ export default {
<div class="float-right">
<gl-button @click="cancelDelete()">{{ __('Cancel') }}</gl-button>
<gl-button
ref="modal-delete-button"
data-method="delete"
:to="destroyPath"
variant="danger"
data-qa-selector="delete_modal_button"
@click="track($options.trackingActions.DELETE_PACKAGE)"
>{{ __('Delete') }}</gl-button
>
</div>
......
export const PackageType = {
CONAN: 'conan',
MAVEN: 'maven',
NPM: 'npm',
};
export const TrackingLabels = {
CODE_INSTRUCTION: 'code_instruction',
MAVEN_INSTALLATION: 'maven_installation',
......
import { __ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime_utility';
import { PackageType, TrackingActions } from './constants';
import { TrackingActions } from './constants';
import { PackageType } from '../shared/constants';
export const trackInstallationTabChange = {
methods: {
......
<script>
import { mapState } from 'vuex';
import { GlTable, GlPagination, GlButton, GlSorting, GlSortingItem, GlModal } from '@gitlab/ui';
import Tracking from '~/tracking';
import { s__, sprintf } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import Icon from '~/vue_shared/components/icon.vue';
import { s__, sprintf } from '~/locale';
import {
LIST_KEY_NAME,
LIST_KEY_PROJECT,
......@@ -18,6 +19,8 @@ import {
LIST_LABEL_CREATED_AT,
LIST_LABEL_ACTIONS,
} from '../constants';
import { TrackingActions } from '../../shared/constants';
import { packageTypeToTrackCategory } from '../../shared/utils';
export default {
components: {
......@@ -30,6 +33,7 @@ export default {
GlModal,
Icon,
},
mixins: [Tracking.mixin()],
data() {
return {
modalId: 'confirm-delete-pacakge',
......@@ -126,6 +130,14 @@ export default {
false,
);
},
tracking() {
const category = this.itemToBeDeleted
? packageTypeToTrackCategory(this.itemToBeDeleted.package_type)
: undefined;
return {
category,
};
},
},
methods: {
onDirectionChange() {
......@@ -140,6 +152,7 @@ export default {
},
deleteItemConfirmation() {
this.$emit('package:delete', this.itemToBeDeleted.id);
this.track(TrackingActions.DELETE_PACKAGE);
this.itemToBeDeleted = null;
},
deleteItemCanceled() {
......
export const PackageType = {
MAVEN: 'maven',
NPM: 'npm',
CONAN: 'conan',
};
export const TrackingActions = {
DELETE_PACKAGE: 'delete_package',
PULL_PACKAGE: 'pull_package',
};
export const TrackingCategories = {
[PackageType.MAVEN]: 'MavenPackages',
[PackageType.NPM]: 'NpmPackages',
[PackageType.CONAN]: 'ConanPackages',
};
import { TrackingCategories } from './constants';
// eslint-disable-next-line import/prefer-default-export
export const packageTypeToTrackCategory = type =>
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
`UI::${TrackingCategories[type]}`;
import { mount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
import Tracking from '~/tracking';
import PackagesApp from 'ee/packages/details/components/app.vue';
import PackageInformation from 'ee/packages/details/components/information.vue';
import NpmInstallation from 'ee/packages/details/components/npm_installation.vue';
import MavenInstallation from 'ee/packages/details/components/maven_installation.vue';
import { mavenPackage, mavenFiles, npmPackage, npmFiles } from '../../mock_data';
import * as SharedUtils from 'ee/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants';
import { mavenPackage, mavenFiles, npmPackage, npmFiles, conanPackage } from '../../mock_data';
describe('PackagesApp', () => {
let wrapper;
......@@ -44,6 +47,7 @@ describe('PackagesApp', () => {
const firstFileDownloadLink = () => wrapper.find('.js-file-download');
const deleteButton = () => wrapper.find('.js-delete-button');
const deleteModal = () => wrapper.find(GlModal);
const modalDeleteButton = () => wrapper.find({ ref: 'modal-delete-button' });
afterEach(() => {
wrapper.destroy();
......@@ -136,4 +140,44 @@ describe('PackagesApp', () => {
expect(deleteModal()).toExist();
});
});
describe('tracking', () => {
let eventSpy;
let utilSpy;
const category = 'foo';
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
});
it('tracking category calls packageTypeToTrackCategory', () => {
createComponent({ packageEntity: conanPackage });
expect(wrapper.vm.tracking.category).toBe(category);
expect(utilSpy).toHaveBeenCalledWith('conan');
});
it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => {
createComponent({ packageEntity: conanPackage, canDelete: true, destroyPath: 'foo' });
deleteButton().trigger('click');
return wrapper.vm.$nextTick().then(() => {
modalDeleteButton().trigger('click');
expect(eventSpy).toHaveBeenCalledWith(
category,
TrackingActions.DELETE_PACKAGE,
expect.any(Object),
);
});
});
it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => {
createComponent({ packageEntity: conanPackage });
firstFileDownloadLink().trigger('click');
expect(eventSpy).toHaveBeenCalledWith(
category,
TrackingActions.PULL_PACKAGE,
expect.any(Object),
);
});
});
});
import Vue from 'vue';
import _ from 'underscore';
import Tracking from '~/tracking';
import { mount } from '@vue/test-utils';
import PackagesList from 'ee/packages/list/components/packages_list.vue';
import * as SharedUtils from 'ee/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants';
import stubChildren from 'helpers/stub_children';
import { packageList } from '../../mock_data';
......@@ -126,6 +129,7 @@ describe('packages_list', () => {
wrapper.vm.deleteItemConfirmation();
expect(wrapper.vm.itemToBeDeleted).toEqual(null);
});
it('deleteItemConfirmation emit package:delete', () => {
wrapper.setData({ itemToBeDeleted: { id: 2 } });
wrapper.vm.deleteItemConfirmation();
......@@ -179,4 +183,30 @@ describe('packages_list', () => {
expect(table.classes()).toContain('b-table-stacked-md');
});
});
describe('tracking', () => {
let eventSpy;
let utilSpy;
const category = 'foo';
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
});
it('tracking category calls packageTypeToTrackCategory', () => {
expect(wrapper.vm.tracking.category).toBe(category);
expect(utilSpy).toHaveBeenCalledWith('conan');
});
it('deleteItemConfirmation calls event', () => {
wrapper.vm.deleteItemConfirmation();
expect(eventSpy).toHaveBeenCalledWith(
category,
TrackingActions.DELETE_PACKAGE,
expect.any(Object),
);
});
});
});
......@@ -50,8 +50,6 @@ export const npmFiles = [
},
];
export const packageList = [mavenPackage, npmPackage];
export const conanPackage = {
conan_metadatum: {
package_channel: 'stable',
......@@ -67,3 +65,5 @@ export const conanPackage = {
updated_at: '',
version: '1.0.0',
};
export const packageList = [mavenPackage, npmPackage, conanPackage];
import { packageTypeToTrackCategory } from 'ee/packages/shared/utils';
import { PackageType, TrackingCategories } from 'ee/packages/shared/constants';
describe('Packages shared utils', () => {
describe('packageTypeToTrackCategory', () => {
it('prepend UI to package category', () => {
expect(packageTypeToTrackCategory()).toMatchInlineSnapshot(`"UI::undefined"`);
});
it.each(Object.keys(PackageType))('returns a correct category string for %s', packageKey => {
const packageName = PackageType[packageKey];
expect(packageTypeToTrackCategory(packageName)).toBe(
`UI::${TrackingCategories[packageName]}`,
);
});
});
});
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