Skip to content
Snippets Groups Projects
Verified Commit d0a14202 authored by Florie Guibert's avatar Florie Guibert :two: Committed by GitLab
Browse files

Merge branch '436480-empty-state-experiment-tracking' into 'master'

Add tracking for issues_mrs_empty_state experiment

See merge request !146482



Merged-by: default avatarFlorie Guibert <fguibert@gitlab.com>
Approved-by: default avatarMarcos Rocha <mrocha@gitlab.com>
Approved-by: default avatarMinahil Nichols <minahilnichols@gitlab.com>
Approved-by: default avatarFlorie Guibert <fguibert@gitlab.com>
Co-authored-by: default avatarSerhii Yarynovskyi <syarynovskyi@gitlab.com>
parents 854aee3a b3134b59
No related branches found
No related tags found
1 merge request!146482Add tracking for issues_mrs_empty_state experiment
Pipeline #1246637665 passed
Showing
with 355 additions and 40 deletions
......@@ -42,6 +42,11 @@ export default {
required: false,
default: undefined,
},
trackImportClick: {
type: Boolean,
required: false,
default: null,
},
},
data() {
return {
......@@ -82,12 +87,18 @@ export default {
v-if="showImportButton"
v-gl-modal="importModalId"
data-testid="import-from-csv-button"
:data-track-action="trackImportClick && 'click_import_csv_project_issues_empty_list_page'"
:data-track-label="trackImportClick && 'import_csv_project_issues_empty_list'"
:data-track-experiment="trackImportClick && 'issues_mrs_empty_state'"
:item="dropdownItems.importCSV"
/>
<gl-disclosure-dropdown-item
v-if="showImportButton && canEdit"
data-testid="import-from-jira-link"
:item="dropdownItems.importFromJIRA"
:data-track-action="trackImportClick && 'click_import_jira_project_issues_empty_list_page'"
:data-track-label="trackImportClick && 'import_jira_project_issues_empty_list'"
:data-track-experiment="trackImportClick && 'issues_mrs_empty_state'"
/>
<csv-export-modal
......
......@@ -33,6 +33,7 @@ export default {
'showNewIssueLink',
'signInPath',
'groupId',
'isProject',
],
props: {
currentTabCount: {
......@@ -65,7 +66,13 @@ export default {
</script>
<template>
<div v-if="isSignedIn">
<div
v-if="isSignedIn"
data-testid="signed-in-empty-state-block"
:data-track-action="isProject && 'render_project_issues_empty_list_page'"
:data-track-label="isProject && 'project_issues_empty_list'"
:data-track-experiment="isProject && 'issues_mrs_empty_state'"
>
<gitlab-experiment name="issues_mrs_empty_state">
<template #candidate>
<empty-state-without-any-issues-experiment
......@@ -83,7 +90,12 @@ export default {
data-testid="issuable-empty-state"
>
<template #description>
<gl-link :href="$options.issuesHelpPagePath">
<gl-link
:href="$options.issuesHelpPagePath"
:data-track-action="isProject && 'click_learn_more_project_issues_empty_list_page'"
:data-track-label="isProject && 'learn_more_project_issues_empty_list'"
:data-track-experiment="isProject && 'issues_mrs_empty_state'"
>
{{ $options.i18n.noIssuesDescription }}
</gl-link>
<p v-if="canCreateProjects">
......@@ -108,6 +120,9 @@ export default {
:href="newIssuePath"
variant="confirm"
class="gl-mx-2 gl-mb-3"
data-track-action="click_new_issue_project_issues_empty_list_page"
data-track-label="new_issue_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
{{ $options.i18n.newIssueLabel }}
</gl-button>
......@@ -121,6 +136,7 @@ export default {
<csv-import-export-buttons
:export-csv-path="exportCsvPathWithQuery"
:issuable-count="currentTabCount"
track-import-click
/>
</gl-disclosure-dropdown>
......@@ -141,7 +157,14 @@ export default {
<p class="gl-text-center gl-mb-0">
<gl-sprintf :message="$options.i18n.jiraIntegrationMessage">
<template #jiraDocsLink="{ content }">
<gl-link :href="jiraIntegrationPath">{{ content }}</gl-link>
<gl-link
:href="jiraIntegrationPath"
:data-track-action="isProject && 'click_jira_int_project_issues_empty_list_page'"
:data-track-label="isProject && 'jira_int_project_issues_empty_list'"
:data-track-experiment="isProject && 'issues_mrs_empty_state'"
>
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
......
......@@ -93,6 +93,9 @@ export default {
:href="newIssuePath"
variant="confirm"
data-testid="empty-state-new-issue-btn"
data-track-action="click_new_issue_project_issues_empty_list_page"
data-track-label="new_issue_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
{{ __('Create a new issue') }}
</gl-button>
......@@ -102,6 +105,9 @@ export default {
button-class="gl-w-full"
variant="default"
:text="__('Email a new issue')"
data-track-action="click_email_issue_project_issues_empty_list_page"
data-track-label="email_issue_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
/>
</div>
......@@ -121,6 +127,9 @@ export default {
v-gl-modal="importModalId"
class="gl-mt-3 gl-ml-0! gl-mb-0!"
data-testid="empty-state-import-csv-btn"
data-track-action="click_import_csv_project_issues_empty_list_page"
data-track-label="import_csv_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
{{ __('Import CSV') }}
</gl-button>
......@@ -130,6 +139,9 @@ export default {
class="gl-mt-3 gl-mb-0!"
:href="projectImportJiraPath"
data-testid="empty-state-import-jira-btn"
data-track-action="click_import_jira_project_issues_empty_list_page"
data-track-label="import_jira_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
{{ __('Import from Jira') }}
</gl-button>
......@@ -137,7 +149,14 @@ export default {
</template>
</gl-card-empty-state-experiment>
<a class="gl-text-decoration-none!" :href="$options.issuesHelpPagePath">
<a
class="gl-text-decoration-none!"
:href="$options.issuesHelpPagePath"
data-testid="empty-state-learn-more-link"
data-track-action="click_learn_more_project_issues_empty_list_page"
data-track-label="learn_more_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
<gl-card-empty-state-experiment
class="gl-h-13 gl-justify-content-center gl-hover-text-blue-600 gl-text-gray-900"
icon="issue-type-issue"
......@@ -157,7 +176,14 @@ export default {
<div
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-justify-content-center"
>
<a class="gl-text-decoration-none!" :href="jiraIntegrationPath">
<a
class="gl-text-decoration-none!"
:href="jiraIntegrationPath"
data-testid="empty-state-jira-int-link"
data-track-action="click_jira_int_project_issues_empty_list_page"
data-track-label="jira_int_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
>
<gl-card-empty-state-experiment
class="gl-h-13 gl-hover-text-blue-600 gl-text-gray-900"
icon="api"
......
......@@ -1080,7 +1080,12 @@ export default {
<gitlab-experiment v-if="showIssuableByEmail" name="issues_mrs_empty_state">
<template #control>
<issuable-by-email class="gl-text-center gl-pt-5 gl-pb-7" />
<issuable-by-email
class="gl-text-center gl-pt-5 gl-pb-7"
data-track-action="click_email_issue_project_issues_empty_list_page"
data-track-label="email_issue_project_issues_empty_list"
data-track-experiment="issues_mrs_empty_state"
/>
</template>
</gitlab-experiment>
</div>
......
......@@ -35,4 +35,4 @@
title: _("There are no closed merge requests"))
- else
= render_if_exists 'shared/empty_states/empty_merge_requests_without_filters', button_path: button_path
= render_if_exists 'shared/empty_states/merge_requests_without_filters', button_path: button_path
- button_path = local_assigns[:button_path]
- button_text = _('New merge request')
- project_tracking_data = @project ? { track_action: 'click_new_mr_project_mrs_empty_list_page',
track_label: 'new_mr_project_mrs_empty_list',
track_experiment: 'issues_mrs_empty_state' } : {}
= render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-merge-requests-md.svg',
empty_state_options: { data: { testid: 'issuable-empty-state' } },
title: _("Merge requests are a place to propose changes you've made to a project and discuss those changes with others")) do |c|
......@@ -13,4 +17,4 @@
title: button_text,
id: 'new_merge_request_link',
variant: :confirm,
data: { testid: 'new-merge-request-button', event_tracking: 'click_new_merge_request_empty_list' }
data: { testid: 'new-merge-request-button', **project_tracking_data }
- button_path = local_assigns[:button_path]
- learn_more_merge_request_url = help_page_url('user/project/merge_requests/creating_merge_requests')
- if show_video_component?(@project)
.gl-text-center.gl-empty-state
%iframe{ class: 'video-container gl-h-auto gl-w-full',
src: 'https://www.youtube-nocookie.com/embed/muozG1gyOqg?si=TondW4RLypjd-aZz',
title: 'Creating and submitting a merge request - The basics',
frameborder: '0',
allow: 'accelerometer; encrypted-media; gyroscope;',
sandbox: 'allow-scripts allow-same-origin allow-presentation',
allowfullscreen: true }
%h4.gl-font-size-h-display.gl-max-w-75.gl-m-auto.gl-pt-8
= _('A merge request (MR) is a proposal to incorporate changes from a source branch to a target branch.')
%p.gl-max-w-75.gl-m-auto.gl-pt-4.gl-pb-5
= _('When you open a merge request, you can visualize and collaborate on the changes before merge.')
.gl-display-flex.gl-flex-direction-column.gl-sm-flex-direction-row.gl-justify-content-center.gl-gap-3
- if button_path
= link_button_to _('Create a new merge request'), button_path,
title: _('Create a new merge request'),
id: 'new_merge_request_link',
variant: :confirm,
data: { testid: "new-merge-request-button", event_tracking: 'click_new_merge_request_empty_list' }
= link_button_to _('Learn more about merge requests'), learn_more_merge_request_url,
title: _('Learn more about merge requests'),
id: 'learn_more_merge_request_link',
target: '_blank'
- else
= render_ce 'shared/empty_states/empty_merge_requests_without_filters', button_path: button_path
- button_path = local_assigns[:button_path]
- learn_more_merge_request_url = help_page_url('user/project/merge_requests/creating_merge_requests')
- project_tracking_data = @project ? { track_action: 'render_project_mrs_empty_list_page',
track_label: 'project_mrs_empty_list',
track_experiment: 'issues_mrs_empty_state' } : {}
%div{ data: project_tracking_data }
- if show_video_component?(@project)
.gl-text-center.gl-empty-state
%iframe{ class: 'video-container gl-h-auto gl-w-full',
src: 'https://www.youtube-nocookie.com/embed/muozG1gyOqg?si=TondW4RLypjd-aZz',
title: 'Creating and submitting a merge request - The basics',
frameborder: '0',
allow: 'accelerometer; encrypted-media; gyroscope;',
sandbox: 'allow-scripts allow-same-origin allow-presentation',
allowfullscreen: true }
%h4.gl-font-size-h-display.gl-max-w-75.gl-m-auto.gl-pt-8
= _('A merge request (MR) is a proposal to incorporate changes from a source branch to a target branch.')
%p.gl-max-w-75.gl-m-auto.gl-pt-4.gl-pb-5
= _('When you open a merge request, you can visualize and collaborate on the changes before merge.')
.gl-display-flex.gl-flex-direction-column.gl-sm-flex-direction-row.gl-justify-content-center.gl-gap-3
- if button_path
= link_button_to _('Create a new merge request'), button_path,
title: _('Create a new merge request'),
id: 'new_merge_request_link',
variant: :confirm,
data: { testid: 'new-merge-request-button',
track_action: 'click_new_mr_project_mrs_empty_list_page',
track_label: 'new_mr_project_mrs_empty_list',
track_experiment: 'issues_mrs_empty_state' }
= link_button_to _('Learn more about merge requests'), learn_more_merge_request_url,
title: _('Learn more about merge requests'),
id: 'learn_more_merge_request_link',
target: '_blank',
data: { track_action: 'click_learn_more_project_mrs_empty_list_page',
track_label: 'learn_more_project_mrs_empty_list',
track_experiment: 'issues_mrs_empty_state' }
- else
= render_ce 'shared/empty_states/merge_requests_without_filters', button_path: button_path
......@@ -4,7 +4,7 @@ module QA
module Page
module MergeRequest
class Index < Page::Base
view 'app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml' do
view 'app/views/shared/empty_states/_merge_requests_without_filters.html.haml' do
element 'new-merge-request-button'
end
......
......@@ -11,7 +11,7 @@ describe('CsvImportExportButtons', () => {
const exportCsvPath = '/gitlab-org/gitlab-test/-/issues/export_csv';
const issuableCount = 10;
function createComponent(injectedProperties = {}) {
function createComponent(injectedProperties = {}, props = {}) {
glModalDirective = jest.fn();
return mountExtended(CsvImportExportButtons, {
directives: {
......@@ -28,6 +28,7 @@ describe('CsvImportExportButtons', () => {
propsData: {
exportCsvPath,
issuableCount,
...props,
},
});
}
......@@ -140,5 +141,62 @@ describe('CsvImportExportButtons', () => {
expect(findImportCsvModal().exists()).toBe(false);
});
});
describe('tracking', () => {
const experimentTracking = { 'data-track-experiment': 'issues_mrs_empty_state' };
const importCsvTracking = {
'data-track-action': 'click_import_csv_project_issues_empty_list_page',
'data-track-label': 'import_csv_project_issues_empty_list',
};
const importJiraTracking = {
'data-track-action': 'click_import_jira_project_issues_empty_list_page',
'data-track-label': 'import_jira_project_issues_empty_list',
};
describe('when the trackImportClick=true', () => {
beforeEach(() => {
wrapper = createComponent(
{ showImportButton: true, canEdit: true },
{ trackImportClick: true },
);
});
it('tracks import CSV button', () => {
expect(findImportCsvButton().attributes()).toMatchObject({
...importCsvTracking,
...experimentTracking,
});
});
it('tracks import Jira link', () => {
expect(findImportFromJiraLink().attributes()).toMatchObject({
...importJiraTracking,
...experimentTracking,
});
});
});
describe('when the trackImportClick=false', () => {
beforeEach(() => {
wrapper = createComponent({ showImportButton: true, canEdit: true });
});
it('does not track import CSV button', () => {
expect(findImportCsvButton().attributes()).not.toMatchObject({
...importCsvTracking,
...experimentTracking,
});
});
it('does not track import Jira link', () => {
expect(findImportFromJiraLink().attributes()).not.toMatchObject({
...importJiraTracking,
...experimentTracking,
});
});
});
});
});
});
......@@ -23,6 +23,8 @@ describe('EmptyStateWithoutAnyIssuesExperiment component', () => {
const findIssuableByEmail = () => wrapper.findComponent(IssuableByEmail);
const findCsvImportButton = () => wrapper.findByTestId('empty-state-import-csv-btn');
const findImportFromJiraButton = () => wrapper.findByTestId('empty-state-import-jira-btn');
const findLearnMoreLink = () => wrapper.findByTestId('empty-state-learn-more-link');
const findJiraIntLink = () => wrapper.findByTestId('empty-state-jira-int-link');
const mountComponent = ({ props = {}, provide = {} } = {}) => {
wrapper = mountExtended(EmptyStateWithoutAnyIssuesExperiment, {
......@@ -156,4 +158,84 @@ describe('EmptyStateWithoutAnyIssuesExperiment component', () => {
});
});
});
describe('tracking', () => {
const experimentTracking = { 'data-track-experiment': 'issues_mrs_empty_state' };
const newIssueButtonTracking = {
'data-track-action': 'click_new_issue_project_issues_empty_list_page',
'data-track-label': 'new_issue_project_issues_empty_list',
};
const issuableByEmailTracking = {
'data-track-action': 'click_email_issue_project_issues_empty_list_page',
'data-track-label': 'email_issue_project_issues_empty_list',
};
const importCsvTracking = {
'data-track-action': 'click_import_csv_project_issues_empty_list_page',
'data-track-label': 'import_csv_project_issues_empty_list',
};
const importJiraTracking = {
'data-track-action': 'click_import_jira_project_issues_empty_list_page',
'data-track-label': 'import_jira_project_issues_empty_list',
};
const learnMoreLinkTracking = {
'data-track-action': 'click_learn_more_project_issues_empty_list_page',
'data-track-label': 'learn_more_project_issues_empty_list',
};
const jiraIntLinkTracking = {
'data-track-action': 'click_jira_int_project_issues_empty_list_page',
'data-track-label': 'jira_int_project_issues_empty_list',
};
beforeEach(() => {
mountComponent();
});
it('tracks new issue button', () => {
expect(findNewIssueButton().attributes()).toMatchObject({
...newIssueButtonTracking,
...experimentTracking,
});
});
it('tracks IssuableByEmail', () => {
expect(findIssuableByEmail().attributes()).toMatchObject({
...issuableByEmailTracking,
...experimentTracking,
});
});
it('tracks import CSV button', () => {
expect(findCsvImportButton().attributes()).toMatchObject({
...importCsvTracking,
...experimentTracking,
});
});
it('tracks import Jira button', () => {
expect(findImportFromJiraButton().attributes()).toMatchObject({
...importJiraTracking,
...experimentTracking,
});
});
it('tracks learn more link', () => {
expect(findLearnMoreLink().attributes()).toMatchObject({
...learnMoreLinkTracking,
...experimentTracking,
});
});
it('tracks Jira integration link', () => {
expect(findJiraIntLink().attributes()).toMatchObject({
...jiraIntLinkTracking,
...experimentTracking,
});
});
});
});
......@@ -27,8 +27,10 @@ describe('EmptyStateWithoutAnyIssues component', () => {
showNewIssueLink: false,
signInPath: 'sign/in/path',
groupId: '',
isProject: false,
};
const findSignedInEmptyStateBlock = () => wrapper.findByTestId('signed-in-empty-state-block');
const findCsvImportExportButtons = () => wrapper.findComponent(CsvImportExportButtons);
const findCsvImportExportDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
......@@ -177,6 +179,89 @@ describe('EmptyStateWithoutAnyIssues component', () => {
});
});
});
describe('tracking', () => {
const experimentTracking = { 'data-track-experiment': 'issues_mrs_empty_state' };
const emptyStateBlockTracking = {
'data-track-action': 'render_project_issues_empty_list_page',
'data-track-label': 'project_issues_empty_list',
};
const issueHelpLinkTracking = {
'data-track-action': 'click_learn_more_project_issues_empty_list_page',
'data-track-label': 'learn_more_project_issues_empty_list',
};
const jiraDocsLinkTracking = {
'data-track-action': 'click_jira_int_project_issues_empty_list_page',
'data-track-label': 'jira_int_project_issues_empty_list',
};
it('tracks new issue link', () => {
mountComponent({ provide: { showNewIssueLink: true } });
expect(findNewIssueLink().attributes()).toMatchObject({
'data-track-action': 'click_new_issue_project_issues_empty_list_page',
'data-track-label': 'new_issue_project_issues_empty_list',
...experimentTracking,
});
});
describe('when the isProject=true', () => {
beforeEach(() => {
mountComponent({ provide: { isProject: true } });
});
it('tracks empty state block', () => {
expect(findSignedInEmptyStateBlock().attributes()).toMatchObject({
...emptyStateBlockTracking,
...experimentTracking,
});
});
it('tracks issue help link', () => {
expect(findIssuesHelpPageLink().attributes()).toMatchObject({
...issueHelpLinkTracking,
...experimentTracking,
});
});
it('tracks Jira docs link', () => {
expect(findJiraDocsLink().attributes()).toMatchObject({
...jiraDocsLinkTracking,
...experimentTracking,
});
});
});
describe('when the isProject=false', () => {
beforeEach(() => {
mountComponent();
});
it('does not track empty state block', () => {
expect(findSignedInEmptyStateBlock().attributes()).not.toMatchObject({
...emptyStateBlockTracking,
...experimentTracking,
});
});
it('does not track issue help link', () => {
expect(findIssuesHelpPageLink().attributes()).not.toMatchObject({
...issueHelpLinkTracking,
...experimentTracking,
});
});
it('does not track Jira docs link', () => {
expect(findJiraDocsLink().attributes()).not.toMatchObject({
...jiraDocsLinkTracking,
...experimentTracking,
});
});
});
});
});
describe('Jira section', () => {
......
......@@ -563,6 +563,16 @@ describe('CE IssuesListApp component', () => {
},
);
it('tracks IssuableByEmail', () => {
wrapper = mountComponent({ provide: { initialEmail: true, canCreateIssue: true } });
expect(findIssuableByEmail().attributes()).toMatchObject({
'data-track-action': 'click_email_issue_project_issues_empty_list_page',
'data-track-label': 'email_issue_project_issues_empty_list',
'data-track-experiment': 'issues_mrs_empty_state',
});
});
describe('when issues_mrs_empty_state candidate experiment', () => {
beforeEach(() => {
stubExperiments({ issues_mrs_empty_state: 'candidate' });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment