Commit d5be2c9a authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera Committed by Martin Wortschack

Refactor table registry modal, tracking mixin

- simplify event handling
- use aliases for import
- add tracking mixin
parent e36c7247
...@@ -8,12 +8,13 @@ import { ...@@ -8,12 +8,13 @@ import {
GlModalDirective, GlModalDirective,
GlEmptyState, GlEmptyState,
} from '@gitlab/ui'; } from '@gitlab/ui';
import createFlash from '../../flash'; import createFlash from '~/flash';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue'; import Tracking from '~/tracking';
import Icon from '../../vue_shared/components/icon.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Icon from '~/vue_shared/components/icon.vue';
import TableRegistry from './table_registry.vue'; import TableRegistry from './table_registry.vue';
import { errorMessages, errorMessagesTypes } from '../constants'; import { DELETE_REPO_ERROR_MESSAGE } from '../constants';
import { __ } from '../../locale'; import { __ } from '~/locale';
export default { export default {
name: 'CollapsibeContainerRegisty', name: 'CollapsibeContainerRegisty',
...@@ -30,6 +31,7 @@ export default { ...@@ -30,6 +31,7 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective, GlModal: GlModalDirective,
}, },
mixins: [Tracking.mixin({})],
props: { props: {
repo: { repo: {
type: Object, type: Object,
...@@ -40,6 +42,10 @@ export default { ...@@ -40,6 +42,10 @@ export default {
return { return {
isOpen: false, isOpen: false,
modalId: `confirm-repo-deletion-modal-${this.repo.id}`, modalId: `confirm-repo-deletion-modal-${this.repo.id}`,
tracking: {
category: document.body.dataset.page,
label: 'registry_repository_delete',
},
}; };
}, },
computed: { computed: {
...@@ -61,15 +67,13 @@ export default { ...@@ -61,15 +67,13 @@ export default {
} }
}, },
handleDeleteRepository() { handleDeleteRepository() {
this.track('confirm_delete', {});
return this.deleteItem(this.repo) return this.deleteItem(this.repo)
.then(() => { .then(() => {
createFlash(__('This container registry has been scheduled for deletion.'), 'notice'); createFlash(__('This container registry has been scheduled for deletion.'), 'notice');
this.fetchRepos(); this.fetchRepos();
}) })
.catch(() => this.showError(errorMessagesTypes.DELETE_REPO)); .catch(() => createFlash(DELETE_REPO_ERROR_MESSAGE));
},
showError(message) {
createFlash(errorMessages[message]);
}, },
}, },
}; };
...@@ -97,10 +101,9 @@ export default { ...@@ -97,10 +101,9 @@ export default {
v-gl-modal="modalId" v-gl-modal="modalId"
:title="s__('ContainerRegistry|Remove repository')" :title="s__('ContainerRegistry|Remove repository')"
:aria-label="s__('ContainerRegistry|Remove repository')" :aria-label="s__('ContainerRegistry|Remove repository')"
data-track-event="click_button"
data-track-label="registry_repository_delete"
class="js-remove-repo btn-inverted" class="js-remove-repo btn-inverted"
variant="danger" variant="danger"
@click="track('click_button', {})"
> >
<icon name="remove" /> <icon name="remove" />
</gl-button> </gl-button>
...@@ -124,7 +127,13 @@ export default { ...@@ -124,7 +127,13 @@ export default {
class="mx-auto my-0" class="mx-auto my-0"
/> />
</div> </div>
<gl-modal :modal-id="modalId" ok-variant="danger" @ok="handleDeleteRepository"> <gl-modal
ref="deleteModal"
:modal-id="modalId"
ok-variant="danger"
@ok="handleDeleteRepository"
@cancel="track('cancel_delete', {})"
>
<template v-slot:modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template> <template v-slot:modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template>
<p <p
v-html=" v-html="
......
<script> <script>
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import { import { GlButton, GlFormCheckbox, GlTooltipDirective, GlModal } from '@gitlab/ui';
GlButton, import Tracking from '~/tracking';
GlFormCheckbox, import { n__, s__, sprintf } from '~/locale';
GlTooltipDirective, import createFlash from '~/flash';
GlModal, import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
GlModalDirective, import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
} from '@gitlab/ui'; import Icon from '~/vue_shared/components/icon.vue';
import { n__, s__, sprintf } from '../../locale'; import timeagoMixin from '~/vue_shared/mixins/timeago';
import createFlash from '../../flash'; import { numberToHumanSize } from '~/lib/utils/number_utils';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue'; import { FETCH_REGISTRY_ERROR_MESSAGE, DELETE_REGISTRY_ERROR_MESSAGE } from '../constants';
import TablePagination from '../../vue_shared/components/pagination/table_pagination.vue';
import Icon from '../../vue_shared/components/icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago';
import { errorMessages, errorMessagesTypes } from '../constants';
import { numberToHumanSize } from '../../lib/utils/number_utils';
export default { export default {
components: { components: {
...@@ -27,7 +22,6 @@ export default { ...@@ -27,7 +22,6 @@ export default {
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
GlModal: GlModalDirective,
}, },
mixins: [timeagoMixin], mixins: [timeagoMixin],
props: { props: {
...@@ -65,12 +59,21 @@ export default { ...@@ -65,12 +59,21 @@ export default {
this.itemsToBeDeleted.length === 0 ? 1 : this.itemsToBeDeleted.length, this.itemsToBeDeleted.length === 0 ? 1 : this.itemsToBeDeleted.length,
); );
}, },
isMultiDelete() {
return this.itemsToBeDeleted.length > 1;
},
tracking() {
return {
property: this.repo.name,
label: this.isMultiDelete ? 'bulk_registry_tag_delete' : 'registry_tag_delete',
};
}, },
mounted() {
this.$refs.deleteModal.$refs.modal.$on('hide', this.removeModalEvents);
}, },
methods: { methods: {
...mapActions(['fetchList', 'deleteItem', 'multiDeleteItems']), ...mapActions(['fetchList', 'deleteItem', 'multiDeleteItems']),
track(action) {
Tracking.event(document.body.dataset.page, action, this.tracking);
},
setModalDescription(itemIndex = -1) { setModalDescription(itemIndex = -1) {
if (itemIndex === -1) { if (itemIndex === -1) {
this.modalDescription = sprintf( this.modalDescription = sprintf(
...@@ -92,17 +95,11 @@ export default { ...@@ -92,17 +95,11 @@ export default {
formatSize(size) { formatSize(size) {
return numberToHumanSize(size); return numberToHumanSize(size);
}, },
removeModalEvents() {
this.$refs.deleteModal.$refs.modal.$off('ok');
},
deleteSingleItem(index) { deleteSingleItem(index) {
this.setModalDescription(index); this.setModalDescription(index);
this.itemsToBeDeleted = [index]; this.itemsToBeDeleted = [index];
this.track('click_button');
this.$refs.deleteModal.$refs.modal.$once('ok', () => { this.$refs.deleteModal.show();
this.removeModalEvents();
this.handleSingleDelete(this.repo.list[index]);
});
}, },
deleteMultipleItems() { deleteMultipleItems() {
this.itemsToBeDeleted = [...this.selectedItems]; this.itemsToBeDeleted = [...this.selectedItems];
...@@ -111,17 +108,14 @@ export default { ...@@ -111,17 +108,14 @@ export default {
} else if (this.selectedItems.length > 1) { } else if (this.selectedItems.length > 1) {
this.setModalDescription(); this.setModalDescription();
} }
this.track('click_button');
this.$refs.deleteModal.$refs.modal.$once('ok', () => { this.$refs.deleteModal.show();
this.removeModalEvents();
this.handleMultipleDelete();
});
}, },
handleSingleDelete(itemToDelete) { handleSingleDelete(itemToDelete) {
this.itemsToBeDeleted = []; this.itemsToBeDeleted = [];
this.deleteItem(itemToDelete) this.deleteItem(itemToDelete)
.then(() => this.fetchList({ repo: this.repo })) .then(() => this.fetchList({ repo: this.repo }))
.catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY)); .catch(() => createFlash(DELETE_REGISTRY_ERROR_MESSAGE));
}, },
handleMultipleDelete() { handleMultipleDelete() {
const { itemsToBeDeleted } = this; const { itemsToBeDeleted } = this;
...@@ -134,19 +128,16 @@ export default { ...@@ -134,19 +128,16 @@ export default {
items: itemsToBeDeleted.map(x => this.repo.list[x].tag), items: itemsToBeDeleted.map(x => this.repo.list[x].tag),
}) })
.then(() => this.fetchList({ repo: this.repo })) .then(() => this.fetchList({ repo: this.repo }))
.catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY)); .catch(() => createFlash(DELETE_REGISTRY_ERROR_MESSAGE));
} else { } else {
this.showError(errorMessagesTypes.DELETE_REGISTRY); createFlash(DELETE_REGISTRY_ERROR_MESSAGE);
} }
}, },
onPageChange(pageNumber) { onPageChange(pageNumber) {
this.fetchList({ repo: this.repo, page: pageNumber }).catch(() => this.fetchList({ repo: this.repo, page: pageNumber }).catch(() =>
this.showError(errorMessagesTypes.FETCH_REGISTRY), createFlash(FETCH_REGISTRY_ERROR_MESSAGE),
); );
}, },
showError(message) {
createFlash(errorMessages[message]);
},
onSelectAllChange() { onSelectAllChange() {
if (this.selectAllChecked) { if (this.selectAllChecked) {
this.deselectAll(); this.deselectAll();
...@@ -179,6 +170,15 @@ export default { ...@@ -179,6 +170,15 @@ export default {
canDeleteRow(item) { canDeleteRow(item) {
return item && item.canDelete && !this.isDeleteDisabled; return item && item.canDelete && !this.isDeleteDisabled;
}, },
onDeletionConfirmed() {
this.track('confirm_delete');
if (this.isMultiDelete) {
this.handleMultipleDelete();
} else {
const index = this.itemsToBeDeleted[0];
this.handleSingleDelete(this.repo.list[index]);
}
},
}, },
}; };
</script> </script>
...@@ -202,12 +202,10 @@ export default { ...@@ -202,12 +202,10 @@ export default {
<th> <th>
<gl-button <gl-button
v-if="canDeleteRepo" v-if="canDeleteRepo"
ref="bulkDeleteButton"
v-gl-tooltip v-gl-tooltip
v-gl-modal="modalId"
:disabled="!selectedItems || selectedItems.length === 0" :disabled="!selectedItems || selectedItems.length === 0"
class="js-delete-registry float-right" class="float-right"
data-track-event="click_button"
data-track-label="bulk_registry_tag_delete"
variant="danger" variant="danger"
:title="s__('ContainerRegistry|Remove selected tags')" :title="s__('ContainerRegistry|Remove selected tags')"
:aria-label="s__('ContainerRegistry|Remove selected tags')" :aria-label="s__('ContainerRegistry|Remove selected tags')"
...@@ -259,11 +257,8 @@ export default { ...@@ -259,11 +257,8 @@ export default {
<td class="content action-buttons"> <td class="content action-buttons">
<gl-button <gl-button
v-if="canDeleteRow(item)" v-if="canDeleteRow(item)"
v-gl-modal="modalId"
:title="s__('ContainerRegistry|Remove tag')" :title="s__('ContainerRegistry|Remove tag')"
:aria-label="s__('ContainerRegistry|Remove tag')" :aria-label="s__('ContainerRegistry|Remove tag')"
data-track-event="click_button"
data-track-label="registry_tag_delete"
variant="danger" variant="danger"
class="js-delete-registry-row float-right btn-inverted btn-border-color btn-icon" class="js-delete-registry-row float-right btn-inverted btn-border-color btn-icon"
@click="deleteSingleItem(index)" @click="deleteSingleItem(index)"
...@@ -282,7 +277,13 @@ export default { ...@@ -282,7 +277,13 @@ export default {
class="js-registry-pagination" class="js-registry-pagination"
/> />
<gl-modal ref="deleteModal" :modal-id="modalId" ok-variant="danger"> <gl-modal
ref="deleteModal"
:modal-id="modalId"
ok-variant="danger"
@ok="onDeletionConfirmed"
@cancel="track('cancel_delete')"
>
<template v-slot:modal-title>{{ modalAction }}</template> <template v-slot:modal-title>{{ modalAction }}</template>
<template v-slot:modal-ok>{{ modalAction }}</template> <template v-slot:modal-ok>{{ modalAction }}</template>
<p v-html="modalDescription"></p> <p v-html="modalDescription"></p>
......
import { __ } from '../locale'; import { __ } from '../locale';
export const errorMessagesTypes = { export const FETCH_REGISTRY_ERROR_MESSAGE = __(
FETCH_REGISTRY: 'FETCH_REGISTRY', 'Something went wrong while fetching the registry list.',
FETCH_REPOS: 'FETCH_REPOS', );
DELETE_REPO: 'DELETE_REPO', export const FETCH_REPOS_ERROR_MESSAGE = __('Something went wrong while fetching the projects.');
DELETE_REGISTRY: 'DELETE_REGISTRY', export const DELETE_REPO_ERROR_MESSAGE = __('Something went wrong on our end.');
}; export const DELETE_REGISTRY_ERROR_MESSAGE = __('Something went wrong on our end.');
export const errorMessages = {
[errorMessagesTypes.FETCH_REGISTRY]: __('Something went wrong while fetching the registry list.'),
[errorMessagesTypes.FETCH_REPOS]: __('Something went wrong while fetching the projects.'),
[errorMessagesTypes.DELETE_REPO]: __('Something went wrong on our end.'),
[errorMessagesTypes.DELETE_REGISTRY]: __('Something went wrong on our end.'),
};
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash'; import createFlash from '~/flash';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { errorMessages, errorMessagesTypes } from '../constants'; import { FETCH_REPOS_ERROR_MESSAGE, FETCH_REGISTRY_ERROR_MESSAGE } from '../constants';
export const fetchRepos = ({ commit, state }) => { export const fetchRepos = ({ commit, state }) => {
commit(types.TOGGLE_MAIN_LOADING); commit(types.TOGGLE_MAIN_LOADING);
...@@ -14,7 +14,7 @@ export const fetchRepos = ({ commit, state }) => { ...@@ -14,7 +14,7 @@ export const fetchRepos = ({ commit, state }) => {
}) })
.catch(() => { .catch(() => {
commit(types.TOGGLE_MAIN_LOADING); commit(types.TOGGLE_MAIN_LOADING);
createFlash(errorMessages[errorMessagesTypes.FETCH_REPOS]); createFlash(FETCH_REPOS_ERROR_MESSAGE);
}); });
}; };
...@@ -30,7 +30,7 @@ export const fetchList = ({ commit }, { repo, page }) => { ...@@ -30,7 +30,7 @@ export const fetchList = ({ commit }, { repo, page }) => {
}) })
.catch(() => { .catch(() => {
commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo); commit(types.TOGGLE_REGISTRY_LIST_LOADING, repo);
createFlash(errorMessages[errorMessagesTypes.FETCH_REGISTRY]); createFlash(FETCH_REGISTRY_ERROR_MESSAGE);
}); });
}; };
......
import * as types from './mutation_types'; import * as types from './mutation_types';
import { parseIntPagination, normalizeHeaders } from '../../lib/utils/common_utils'; import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
export default { export default {
[types.SET_MAIN_ENDPOINT](state, endpoint) { [types.SET_MAIN_ENDPOINT](state, endpoint) {
Object.assign(state, { endpoint }); state.endpoint = endpoint;
}, },
[types.SET_IS_DELETE_DISABLED](state, isDeleteDisabled) { [types.SET_IS_DELETE_DISABLED](state, isDeleteDisabled) {
Object.assign(state, { isDeleteDisabled }); state.isDeleteDisabled = isDeleteDisabled;
}, },
[types.SET_REPOS_LIST](state, list) { [types.SET_REPOS_LIST](state, list) {
Object.assign(state, { state.repos = list.map(el => ({
repos: list.map(el => ({
canDelete: Boolean(el.destroy_path), canDelete: Boolean(el.destroy_path),
destroyPath: el.destroy_path, destroyPath: el.destroy_path,
id: el.id, id: el.id,
...@@ -22,12 +21,11 @@ export default { ...@@ -22,12 +21,11 @@ export default {
name: el.path, name: el.path,
tagsPath: el.tags_path, tagsPath: el.tags_path,
projectId: el.project_id, projectId: el.project_id,
})), }));
});
}, },
[types.TOGGLE_MAIN_LOADING](state) { [types.TOGGLE_MAIN_LOADING](state) {
Object.assign(state, { isLoading: !state.isLoading }); state.isLoading = !state.isLoading;
}, },
[types.SET_REGISTRY_LIST](state, { repo, resp, headers }) { [types.SET_REGISTRY_LIST](state, { repo, resp, headers }) {
......
---
title: Add event tracking to container registry
merge_request: 19772
author:
type: changed
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import collapsibleComponent from '~/registry/components/collapsible_container.vue';
import { repoPropsData } from '../mock_data';
import createFlash from '~/flash'; import createFlash from '~/flash';
import Tracking from '~/tracking';
import collapsibleComponent from '~/registry/components/collapsible_container.vue';
import * as getters from '~/registry/stores/getters'; import * as getters from '~/registry/stores/getters';
import { repoPropsData } from '../mock_data';
jest.mock('~/flash.js'); jest.mock('~/flash.js');
...@@ -16,9 +17,10 @@ describe('collapsible registry container', () => { ...@@ -16,9 +17,10 @@ describe('collapsible registry container', () => {
let wrapper; let wrapper;
let store; let store;
const findDeleteBtn = w => w.find('.js-remove-repo'); const findDeleteBtn = (w = wrapper) => w.find('.js-remove-repo');
const findContainerImageTags = w => w.find('.container-image-tags'); const findContainerImageTags = (w = wrapper) => w.find('.container-image-tags');
const findToggleRepos = w => w.findAll('.js-toggle-repo'); const findToggleRepos = (w = wrapper) => w.findAll('.js-toggle-repo');
const findDeleteModal = (w = wrapper) => w.find({ ref: 'deleteModal' });
const mountWithStore = config => mount(collapsibleComponent, { ...config, store, localVue }); const mountWithStore = config => mount(collapsibleComponent, { ...config, store, localVue });
...@@ -124,4 +126,45 @@ describe('collapsible registry container', () => { ...@@ -124,4 +126,45 @@ describe('collapsible registry container', () => {
expect(deleteBtn.exists()).toBe(false); expect(deleteBtn.exists()).toBe(false);
}); });
}); });
describe('tracking', () => {
const category = 'mock_page';
beforeEach(() => {
jest.spyOn(Tracking, 'event');
wrapper.vm.deleteItem = jest.fn().mockResolvedValue();
wrapper.vm.fetchRepos = jest.fn();
wrapper.setData({
tracking: {
...wrapper.vm.tracking,
category,
},
});
});
it('send an event when delete button is clicked', () => {
const deleteBtn = findDeleteBtn();
deleteBtn.trigger('click');
expect(Tracking.event).toHaveBeenCalledWith(category, 'click_button', {
label: 'registry_repository_delete',
category,
});
});
it('send an event when cancel is pressed on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('cancel');
expect(Tracking.event).toHaveBeenCalledWith(category, 'cancel_delete', {
label: 'registry_repository_delete',
category,
});
});
it('send an event when confirm is clicked on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('ok');
expect(Tracking.event).toHaveBeenCalledWith(category, 'confirm_delete', {
label: 'registry_repository_delete',
category,
});
});
});
}); });
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import tableRegistry from '~/registry/components/table_registry.vue';
import { mount, createLocalVue } from '@vue/test-utils'; import { mount, createLocalVue } from '@vue/test-utils';
import createFlash from '~/flash';
import Tracking from '~/tracking';
import tableRegistry from '~/registry/components/table_registry.vue';
import { repoPropsData } from '../mock_data'; import { repoPropsData } from '../mock_data';
import * as getters from '~/registry/stores/getters'; import * as getters from '~/registry/stores/getters';
jest.mock('~/flash');
const [firstImage, secondImage] = repoPropsData.list; const [firstImage, secondImage] = repoPropsData.list;
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -15,11 +19,12 @@ describe('table registry', () => { ...@@ -15,11 +19,12 @@ describe('table registry', () => {
let wrapper; let wrapper;
let store; let store;
const findSelectAllCheckbox = w => w.find('.js-select-all-checkbox > input'); const findSelectAllCheckbox = (w = wrapper) => w.find('.js-select-all-checkbox > input');
const findSelectCheckboxes = w => w.findAll('.js-select-checkbox > input'); const findSelectCheckboxes = (w = wrapper) => w.findAll('.js-select-checkbox > input');
const findDeleteButton = w => w.find('.js-delete-registry'); const findDeleteButton = (w = wrapper) => w.find({ ref: 'bulkDeleteButton' });
const findDeleteButtonsRow = w => w.findAll('.js-delete-registry-row'); const findDeleteButtonsRow = (w = wrapper) => w.findAll('.js-delete-registry-row');
const findPagination = w => w.find('.js-registry-pagination'); const findPagination = (w = wrapper) => w.find('.js-registry-pagination');
const findDeleteModal = (w = wrapper) => w.find({ ref: 'deleteModal' });
const bulkDeletePath = 'path'; const bulkDeletePath = 'path';
const mountWithStore = config => mount(tableRegistry, { ...config, store, localVue }); const mountWithStore = config => mount(tableRegistry, { ...config, store, localVue });
...@@ -139,7 +144,7 @@ describe('table registry', () => { ...@@ -139,7 +144,7 @@ describe('table registry', () => {
}, },
}); });
wrapper.vm.handleMultipleDelete(); wrapper.vm.handleMultipleDelete();
expect(wrapper.vm.showError).toHaveBeenCalled(); expect(createFlash).toHaveBeenCalled();
}); });
}); });
...@@ -169,6 +174,27 @@ describe('table registry', () => { ...@@ -169,6 +174,27 @@ describe('table registry', () => {
}); });
}); });
describe('modal event handlers', () => {
beforeEach(() => {
wrapper.vm.handleSingleDelete = jest.fn();
wrapper.vm.handleMultipleDelete = jest.fn();
});
it('on ok when one item is selected should call singleDelete', () => {
wrapper.setData({ itemsToBeDeleted: [0] });
wrapper.vm.onDeletionConfirmed();
expect(wrapper.vm.handleSingleDelete).toHaveBeenCalledWith(repoPropsData.list[0]);
expect(wrapper.vm.handleMultipleDelete).not.toHaveBeenCalled();
});
it('on ok when multiple items are selected should call muultiDelete', () => {
wrapper.setData({ itemsToBeDeleted: [0, 1, 2] });
wrapper.vm.onDeletionConfirmed();
expect(wrapper.vm.handleMultipleDelete).toHaveBeenCalled();
expect(wrapper.vm.handleSingleDelete).not.toHaveBeenCalled();
});
});
describe('pagination', () => { describe('pagination', () => {
const repo = { const repo = {
repoPropsData, repoPropsData,
...@@ -265,4 +291,83 @@ describe('table registry', () => { ...@@ -265,4 +291,83 @@ describe('table registry', () => {
expect(deleteBtns.length).toBe(0); expect(deleteBtns.length).toBe(0);
}); });
}); });
describe('event tracking', () => {
const mockPageName = 'mock_page';
beforeEach(() => {
jest.spyOn(Tracking, 'event');
wrapper.vm.handleSingleDelete = jest.fn();
wrapper.vm.handleMultipleDelete = jest.fn();
document.body.dataset.page = mockPageName;
});
afterEach(() => {
document.body.dataset.page = null;
});
describe('single tag delete', () => {
beforeEach(() => {
wrapper.setData({ itemsToBeDeleted: [0] });
});
it('send an event when delete button is clicked', () => {
const deleteBtn = findDeleteButtonsRow();
deleteBtn.at(0).trigger('click');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'click_button', {
label: 'registry_tag_delete',
property: 'foo',
});
});
it('send an event when cancel is pressed on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('cancel');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'cancel_delete', {
label: 'registry_tag_delete',
property: 'foo',
});
});
it('send an event when confirm is clicked on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('ok');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'confirm_delete', {
label: 'registry_tag_delete',
property: 'foo',
});
});
});
describe('bulk tag delete', () => {
beforeEach(() => {
const items = [0, 1, 2];
wrapper.setData({ itemsToBeDeleted: items, selectedItems: items });
});
it('send an event when delete button is clicked', () => {
const deleteBtn = findDeleteButton();
deleteBtn.vm.$emit('click');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'click_button', {
label: 'bulk_registry_tag_delete',
property: 'foo',
});
});
it('send an event when cancel is pressed on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('cancel');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'cancel_delete', {
label: 'bulk_registry_tag_delete',
property: 'foo',
});
});
it('send an event when confirm is clicked on modal', () => {
const deleteModal = findDeleteModal();
deleteModal.vm.$emit('ok');
expect(Tracking.event).toHaveBeenCalledWith(mockPageName, 'confirm_delete', {
label: 'bulk_registry_tag_delete',
property: 'foo',
});
});
});
});
}); });
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