From 7f064388333cba5eb9e89a99c528b33a8ceb2551 Mon Sep 17 00:00:00 2001
From: Serhii Yarynovskyi <syarynovskyi@gitlab.com>
Date: Fri, 29 Mar 2024 11:27:58 +0200
Subject: [PATCH 1/2] Add tracking for issues_mrs_empty_state experiment

---
 .../components/csv_import_export_buttons.vue  | 11 +++++
 .../empty_state_without_any_issues.vue        | 28 +++++++++++--
 ...ty_state_without_any_issues_experiment.vue | 28 ++++++++++++-
 .../list/components/issues_list_app.vue       |  7 +++-
 .../empty_states/_merge_requests.html.haml    |  2 +-
 ..._merge_requests_without_filters.html.haml} |  6 ++-
 ...y_merge_requests_without_filters.html.haml | 30 --------------
 .../_merge_requests_without_filters.html.haml | 41 +++++++++++++++++++
 qa/qa/page/merge_request/index.rb             |  2 +-
 .../empty_state_without_any_issues_spec.js    |  1 +
 10 files changed, 117 insertions(+), 39 deletions(-)
 rename app/views/shared/empty_states/{_empty_merge_requests_without_filters.html.haml => _merge_requests_without_filters.html.haml} (71%)
 delete mode 100644 ee/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml
 create mode 100644 ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml

diff --git a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
index 8e2ed63613dd28..68614aa513dc1e 100644
--- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
+++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue
@@ -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
diff --git a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
index 382bb845311396..999eff4de2f2ac 100644
--- a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
+++ b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
@@ -33,6 +33,7 @@ export default {
     'showNewIssueLink',
     'signInPath',
     'groupId',
+    'isProject',
   ],
   props: {
     currentTabCount: {
@@ -65,7 +66,12 @@ export default {
 </script>
 
 <template>
-  <div v-if="isSignedIn">
+  <div
+    v-if="isSignedIn"
+    :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 +89,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 +119,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 +135,7 @@ export default {
                 <csv-import-export-buttons
                   :export-csv-path="exportCsvPathWithQuery"
                   :issuable-count="currentTabCount"
+                  track-import-click
                 />
               </gl-disclosure-dropdown>
 
@@ -141,7 +156,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>
diff --git a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
index 37fc8b97489303..27fee097f79069 100644
--- a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
+++ b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
@@ -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,13 @@ 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-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 +175,13 @@ 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-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"
diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue
index a87b6b65416e94..464fa7612da784 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -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>
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index ecb4959aef9a77..4a55d908eb0ddc 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -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
diff --git a/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml b/app/views/shared/empty_states/_merge_requests_without_filters.html.haml
similarity index 71%
rename from app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml
rename to app/views/shared/empty_states/_merge_requests_without_filters.html.haml
index 017788e5926da6..66cd2f6719d794 100644
--- a/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml
+++ b/app/views/shared/empty_states/_merge_requests_without_filters.html.haml
@@ -1,6 +1,10 @@
 - 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 }
diff --git a/ee/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml b/ee/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml
deleted file mode 100644
index 22e02908ad2d72..00000000000000
--- a/ee/app/views/shared/empty_states/_empty_merge_requests_without_filters.html.haml
+++ /dev/null
@@ -1,30 +0,0 @@
-- 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
diff --git a/ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml b/ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml
new file mode 100644
index 00000000000000..86de5fdaa5f422
--- /dev/null
+++ b/ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml
@@ -0,0 +1,41 @@
+- 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
diff --git a/qa/qa/page/merge_request/index.rb b/qa/qa/page/merge_request/index.rb
index 677f0e1504688d..5c82a964e89468 100644
--- a/qa/qa/page/merge_request/index.rb
+++ b/qa/qa/page/merge_request/index.rb
@@ -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
 
diff --git a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
index 16db1a6098b1e6..52d58da990283c 100644
--- a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
+++ b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
@@ -27,6 +27,7 @@ describe('EmptyStateWithoutAnyIssues component', () => {
     showNewIssueLink: false,
     signInPath: 'sign/in/path',
     groupId: '',
+    isProject: true,
   };
 
   const findCsvImportExportButtons = () => wrapper.findComponent(CsvImportExportButtons);
-- 
GitLab


From f3de1ce0ca7799fa558f69cd7f9c8c8398e20548 Mon Sep 17 00:00:00 2001
From: Serhii Yarynovskyi <syarynovskyi@gitlab.com>
Date: Mon, 8 Apr 2024 16:16:54 +0300
Subject: [PATCH 2/2] Add tracking tests

---
 .../empty_state_without_any_issues.vue        |  1 +
 ...ty_state_without_any_issues_experiment.vue |  2 +
 .../csv_import_export_buttons_spec.js         | 60 ++++++++++++-
 ...tate_without_any_issues_experiment_spec.js | 82 ++++++++++++++++++
 .../empty_state_without_any_issues_spec.js    | 86 ++++++++++++++++++-
 .../list/components/issues_list_app_spec.js   | 10 +++
 6 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
index 999eff4de2f2ac..48d6545b21e4b9 100644
--- a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
+++ b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues.vue
@@ -68,6 +68,7 @@ export default {
 <template>
   <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'"
diff --git a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
index 27fee097f79069..8bf50e30112ce2 100644
--- a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
+++ b/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue
@@ -152,6 +152,7 @@ export default {
         <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"
@@ -178,6 +179,7 @@ export default {
         <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"
diff --git a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
index 4b4deafcabd33d..3d1f00d624bcd7 100644
--- a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
+++ b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js
@@ -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,
+          });
+        });
+      });
+    });
   });
 });
diff --git a/spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js b/spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js
index 64a2cc7c933766..5251906f21fc63 100644
--- a/spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js
+++ b/spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js
@@ -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,
+      });
+    });
+  });
 });
diff --git a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
index 52d58da990283c..004e5fd9356af5 100644
--- a/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
+++ b/spec/frontend/issues/list/components/empty_state_without_any_issues_spec.js
@@ -27,9 +27,10 @@ describe('EmptyStateWithoutAnyIssues component', () => {
     showNewIssueLink: false,
     signInPath: 'sign/in/path',
     groupId: '',
-    isProject: true,
+    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);
@@ -178,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', () => {
diff --git a/spec/frontend/issues/list/components/issues_list_app_spec.js b/spec/frontend/issues/list/components/issues_list_app_spec.js
index b5c03cd0eda3c6..1d9c9a1dbe43c0 100644
--- a/spec/frontend/issues/list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues/list/components/issues_list_app_spec.js
@@ -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' });
-- 
GitLab