From e63ee4fb40f484ddc6c04876a3ec31c074b3b52c Mon Sep 17 00:00:00 2001 From: Jay Montal <jmontal@gitlab.com> Date: Thu, 4 Jul 2024 03:57:25 +0000 Subject: [PATCH] Remove `issues_mrs_empty_state` feature - Feature flag controlled an experiment - Experiment deemed invalidated, as such we want to remove this feature completely Changelog: removed EE: true --- .rubocop_todo/gitlab/bounded_contexts.yml | 1 - .../components/csv_import_export_buttons.vue | 6 - .../issuable/components/issuable_by_email.vue | 21 +- .../empty_state_without_any_issues.vue | 187 ++++++-------- ...ty_state_without_any_issues_experiment.vue | 202 --------------- .../gl_card_empty_state_experiment.vue | 34 --- .../list/components/issues_list_app.vue | 19 +- .../page_bundles/issuable_list.scss | 7 - .../empty_states/_merge_requests.html.haml | 14 +- .../_merge_requests_without_filters.html.haml | 20 -- .../concerns/iframe_youtube_video_csp.rb | 16 -- .../ee/projects/issues_controller.rb | 8 - .../ee/projects/merge_requests_controller.rb | 1 - .../issues_mrs_empty_state_experiment.rb | 27 -- ee/app/helpers/ee/merge_requests_helper.rb | 12 - .../_merge_requests_without_filters.html.haml | 41 --- .../experiment/issues_mrs_empty_state.yml | 9 - .../issues_mrs_empty_state_experiment_spec.rb | 53 ---- .../issues/iframe_youtube_video_csp_spec.rb | 22 -- .../helpers/ee/merge_requests_helper_spec.rb | 58 ----- locale/gitlab.pot | 33 --- qa/qa/page/merge_request/index.rb | 2 +- .../csv_import_export_buttons_spec.js | 57 ----- .../components/issuable_by_email_spec.js | 17 +- ...tate_without_any_issues_experiment_spec.js | 241 ------------------ .../empty_state_without_any_issues_spec.js | 103 -------- .../gl_card_empty_state_experiment_spec.js | 35 --- .../list/components/issues_list_app_spec.js | 19 -- 28 files changed, 105 insertions(+), 1160 deletions(-) delete mode 100644 app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue delete mode 100644 app/assets/javascripts/issues/list/components/gl_card_empty_state_experiment.vue delete mode 100644 app/views/shared/empty_states/_merge_requests_without_filters.html.haml delete mode 100644 ee/app/controllers/concerns/iframe_youtube_video_csp.rb delete mode 100644 ee/app/experiments/issues_mrs_empty_state_experiment.rb delete mode 100644 ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml delete mode 100644 ee/config/feature_flags/experiment/issues_mrs_empty_state.yml delete mode 100644 ee/spec/experiments/issues_mrs_empty_state_experiment_spec.rb delete mode 100644 ee/spec/features/projects/issues/iframe_youtube_video_csp_spec.rb delete mode 100644 spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js delete mode 100644 spec/frontend/issues/list/components/gl_card_empty_state_experiment_spec.js diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml index a22fb77568373..ef85ce792d918 100644 --- a/.rubocop_todo/gitlab/bounded_contexts.yml +++ b/.rubocop_todo/gitlab/bounded_contexts.yml @@ -2219,7 +2219,6 @@ Gitlab/BoundedContexts: - 'ee/app/events/epics/epic_updated_event.rb' - 'ee/app/events/namespace_settings/ai_related_settings_changed_event.rb' - 'ee/app/experiments/ee/application_experiment.rb' - - 'ee/app/experiments/issues_mrs_empty_state_experiment.rb' - 'ee/app/experiments/project_templates_during_registration_experiment.rb' - 'ee/app/experiments/signup_intent_step_one_experiment.rb' - 'ee/app/finders/app_sec/fuzzing/coverage/corpuses_finder.rb' 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 68614aa513dc1..eb81a21c6057e 100644 --- a/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue +++ b/app/assets/javascripts/issuable/components/csv_import_export_buttons.vue @@ -87,18 +87,12 @@ 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/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue index 647339d3dc2e2..71ec5544c3486 100644 --- a/app/assets/javascripts/issuable/components/issuable_by_email.vue +++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue @@ -52,23 +52,6 @@ export default { default: '', }, }, - props: { - buttonClass: { - type: String, - required: false, - default: null, - }, - variant: { - type: String, - required: false, - default: 'link', - }, - text: { - type: String, - required: false, - default: __('Email a new %{name} to this project'), - }, - }, data() { return { email: this.initialEmail, @@ -107,8 +90,8 @@ export default { <template> <div> - <gl-button v-gl-modal="$options.modalId" :class="buttonClass" :variant="variant" - ><gl-sprintf :message="text" + <gl-button v-gl-modal="$options.modalId" variant="link" + ><gl-sprintf :message="__('Email a new %{name} to this project')" ><template #name>{{ issuableName }}</template></gl-sprintf ></gl-button > 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 6a75e2bdf1e98..99a9f1711143a 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 @@ -5,9 +5,7 @@ import { helpPagePath } from '~/helpers/help_page_helper'; import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue'; import { s__ } from '~/locale'; import NewResourceDropdown from '~/vue_shared/components/new_resource_dropdown/new_resource_dropdown.vue'; -import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; import { hasNewIssueDropdown } from '../has_new_issue_dropdown_mixin'; -import EmptyStateWithoutAnyIssuesExperiment from './empty_state_without_any_issues_experiment.vue'; export default { i18n: { @@ -26,8 +24,6 @@ export default { GlLink, GlSprintf, NewResourceDropdown, - GitlabExperiment, - EmptyStateWithoutAnyIssuesExperiment, }, mixins: [hasNewIssueDropdown()], inject: [ @@ -76,111 +72,92 @@ export default { data-testid="signed-in-empty-state-block" :data-track-action="isProject && 'render'" :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 - :show-csv-buttons="showCsvButtons" - :show-issuable-by-email="showIssuableByEmail" - /> - </template> - - <template #control> - <div> - <gl-empty-state - :title="__('Use issues to collaborate on ideas, solve problems, and plan work')" - :svg-path="$options.emptyStateSvg" - :svg-height="150" - data-testid="issuable-empty-state" + <div> + <gl-empty-state + :title="__('Use issues to collaborate on ideas, solve problems, and plan work')" + :svg-path="$options.emptyStateSvg" + :svg-height="150" + data-testid="issuable-empty-state" + > + <template #description> + <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'" + > + {{ __('Learn more about issues.') }} + </gl-link> + <p v-if="canCreateProjects"> + <strong>{{ + __('Issues exist in projects, so to create an issue, first create a project.') + }}</strong> + </p> + </template> + <template #actions> + <gl-button + v-if="canCreateProjects" + :href="newProjectPath" + variant="confirm" + class="gl-mx-2 gl-mb-3" + > + {{ __('New project') }} + </gl-button> + <gl-button + v-if="showNewIssueLink" + :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" > - <template #description> - <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'" - > - {{ __('Learn more about issues.') }} - </gl-link> - <p v-if="canCreateProjects"> - <strong>{{ - __('Issues exist in projects, so to create an issue, first create a project.') - }}</strong> - </p> - </template> - <template #actions> - <!-- This component is shared between groups and projects issues list - Now issues_mrs_empty_state experiment is run only for projects page - If this experiment is successful new project buttons from 'control' should be - moved to 'candidate' template to take affect for groups page as well --> - <gl-button - v-if="canCreateProjects" - :href="newProjectPath" - variant="confirm" - class="gl-mx-2 gl-mb-3" - > - {{ __('New project') }} - </gl-button> - <gl-button - v-if="showNewIssueLink" - :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" - > - {{ __('New issue') }} - </gl-button> + {{ __('New issue') }} + </gl-button> - <gl-disclosure-dropdown - v-if="showCsvButtons" - class="gl-mx-2 gl-mb-3" - :toggle-text="__('Import issues')" - data-testid="import-issues-dropdown" - > - <csv-import-export-buttons - :export-csv-path="exportCsvPathWithQuery" - :issuable-count="currentTabCount" - track-import-click - /> - </gl-disclosure-dropdown> + <gl-disclosure-dropdown + v-if="showCsvButtons" + class="gl-mx-2 gl-mb-3" + :toggle-text="__('Import issues')" + data-testid="import-issues-dropdown" + > + <csv-import-export-buttons + :export-csv-path="exportCsvPathWithQuery" + :issuable-count="currentTabCount" + track-import-click + /> + </gl-disclosure-dropdown> - <new-resource-dropdown - v-if="showNewIssueDropdown" - class="gl-align-self-center gl-mx-2 gl-mb-3" - :query="$options.searchProjectsQuery" - :query-variables="newIssueDropdownQueryVariables" - :extract-projects="extractProjects" - :group-id="groupId" - /> - </template> - </gl-empty-state> - <hr /> - <p class="gl-text-center gl-font-bold gl-mb-0"> - {{ s__('JiraService|Using Jira for issue tracking?') }} - </p> - <p class="gl-text-center gl-mb-0"> - <gl-sprintf :message="$options.i18n.jiraIntegrationMessage"> - <template #jiraDocsLink="{ content }"> - <gl-link - :href="$options.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> - <p class="gl-text-center gl-text-secondary"> - {{ s__('JiraService|This feature requires a Premium plan.') }} - </p> - </div> - </template> - </gitlab-experiment> + <new-resource-dropdown + v-if="showNewIssueDropdown" + class="gl-self-center gl-mx-2 gl-mb-3" + :query="$options.searchProjectsQuery" + :query-variables="newIssueDropdownQueryVariables" + :extract-projects="extractProjects" + :group-id="groupId" + /> + </template> + </gl-empty-state> + <hr /> + <p class="gl-text-center gl-font-bold gl-mb-0"> + {{ s__('JiraService|Using Jira for issue tracking?') }} + </p> + <p class="gl-text-center gl-mb-0"> + <gl-sprintf :message="$options.i18n.jiraIntegrationMessage"> + <template #jiraDocsLink="{ content }"> + <gl-link + :href="$options.jiraIntegrationPath" + :data-track-action="isProject && 'click_jira_int_project_issues_empty_list_page'" + :data-track-label="isProject && 'jira_int_project_issues_empty_list'" + > + {{ content }} + </gl-link> + </template> + </gl-sprintf> + </p> + <p class="gl-text-center gl-text-secondary"> + {{ s__('JiraService|This feature requires a Premium plan.') }} + </p> + </div> </div> <gl-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 deleted file mode 100644 index 786d790e195e3..0000000000000 --- a/app/assets/javascripts/issues/list/components/empty_state_without_any_issues_experiment.vue +++ /dev/null @@ -1,202 +0,0 @@ -<script> -import { GlButton, GlModalDirective, GlIcon } from '@gitlab/ui'; -import { TYPE_ISSUE } from '~/issues/constants'; -import { helpPagePath } from '~/helpers/help_page_helper'; -import IssuableByEmail from '~/issuable/components/issuable_by_email.vue'; -import CsvImportModal from '~/issuable/components/csv_import_modal.vue'; -import GlCardEmptyStateExperiment from './gl_card_empty_state_experiment.vue'; - -export default { - issuesHelpPagePath: helpPagePath('user/project/issues/index'), - jiraIntegrationPath: helpPagePath('integration/jira/issues', { anchor: 'view-jira-issues' }), - components: { - GlCardEmptyStateExperiment, - GlButton, - GlIcon, - IssuableByEmail, - CsvImportModal, - }, - directives: { - GlModal: GlModalDirective, - }, - inject: { - newIssuePath: { - default: null, - }, - showNewIssueLink: { - default: false, - }, - showImportButton: { - default: false, - }, - canEdit: { - default: false, - }, - projectImportJiraPath: { - default: null, - }, - }, - props: { - showCsvButtons: { - type: Boolean, - required: false, - default: false, - }, - showIssuableByEmail: { - type: Boolean, - required: false, - default: false, - }, - }, - computed: { - importModalId() { - return `${TYPE_ISSUE}-import-modal`; - }, - }, -}; -</script> - -<template> - <div class="gl-text-center gl-empty-state"> - <iframe - class="video-container gl-h-auto gl-w-full" - src="https://www.youtube-nocookie.com/embed/-4SGhGpwZDY?si=Ym-29hpY22cgdGdH" - title="Create an Issue - The basics" - frameborder="0" - allow="accelerometer; encrypted-media; gyroscope;" - sandbox="allow-scripts allow-same-origin allow-presentation" - data-testid="create-an-issue-iframe-video" - allowfullscreen - ></iframe> - - <h1 class="gl-font-size-h-display gl-max-w-75 gl-m-auto gl-pt-8"> - {{ __('Use issues to collaborate on ideas, solve problems, and plan work') }} - </h1> - - <p class="gl-max-w-75 gl-m-auto gl-pt-4 gl-pb-5"> - {{ - __( - 'With issues you can discuss the implementation of an idea, track tasks and work status, elaborate on code implementations, and accept feature proposals, questions, support requests, or bug reports.', - ) - }} - </p> - - <div - class="gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-center gl-gap-3" - > - <gl-button - v-if="showNewIssueLink" - :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> - - <issuable-by-email - v-if="showIssuableByEmail" - 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> - - <div class="gl-display-flex gl-flex-direction-column gl-gap-6 gl-max-w-88 gl-mx-auto gl-pt-9"> - <div - class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-justify-content-center gl-gap-6" - > - <gl-card-empty-state-experiment v-if="showCsvButtons && showImportButton" icon="download"> - <template #header> - {{ __('Import existing issues') }} - </template> - <template #body> - <csv-import-modal :modal-id="importModalId" /> - - <div class="gl-display-flex gl-flex-direction-column gl-sm-flex-direction-row gl-gap-3"> - <gl-button - 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> - - <gl-button - v-if="canEdit" - 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> - </div> - </template> - </gl-card-empty-state-experiment> - - <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" - > - <template #header> - {{ __('Learn more about issues') }} - <gl-icon class="gl-display-inline gl-ml-2" name="arrow-right" /> - </template> - - <template #body> - <span class="gl-text-gray-900">{{ __('Read our documentation') }}</span> - </template> - </gl-card-empty-state-experiment> - </a> - </div> - - <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="$options.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" - > - <template #header> - {{ __('Enable Jira integration') }} - <gl-icon class="gl-display-inline gl-ml-2" name="arrow-right" /> - </template> - - <template #body> - <span class="gl-text-gray-900"> - {{ __('This feature is only available on paid plans.') }} - </span> - </template> - </gl-card-empty-state-experiment> - </a> - </div> - </div> - </div> -</template> diff --git a/app/assets/javascripts/issues/list/components/gl_card_empty_state_experiment.vue b/app/assets/javascripts/issues/list/components/gl_card_empty_state_experiment.vue deleted file mode 100644 index 341a5f38a8e06..0000000000000 --- a/app/assets/javascripts/issues/list/components/gl_card_empty_state_experiment.vue +++ /dev/null @@ -1,34 +0,0 @@ -<script> -import { GlCard, GlIcon } from '@gitlab/ui'; - -export default { - components: { - GlCard, - GlIcon, - }, - props: { - icon: { - type: String, - required: true, - }, - }, -}; -</script> - -<template> - <gl-card class="gl-text-left gl-hover-bg-blue-50"> - <div class="gl-display-flex gl-gap-4"> - <div class="gl-display-flex gl-my-auto gl-bg-blue-100 gl-rounded-full gl-min-w-8 gl-min-h-8"> - <gl-icon class="gl-display-flex gl-m-auto gl-text-gray-900" :name="icon" /> - </div> - - <div class="gl-w-31"> - <p class="gl-heading-4 gl-mb-1!"> - <slot name="header"></slot> - </p> - - <slot name="body"></slot> - </div> - </div> - </gl-card> -</template> 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 85da51b4e6e0d..efeebdb5b8960 100644 --- a/app/assets/javascripts/issues/list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue @@ -73,7 +73,6 @@ import NewResourceDropdown from '~/vue_shared/components/new_resource_dropdown/n import deleteWorkItemMutation from '~/work_items/graphql/delete_work_item.mutation.graphql'; import { WORK_ITEM_TYPE_ENUM_OBJECTIVE } from '~/work_items/constants'; import WorkItemDrawer from '~/work_items/components/work_item_drawer.vue'; -import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; import { CREATED_DESC, defaultTypeTokenOptions, @@ -150,7 +149,6 @@ export default { IssueCardTimeInfo, NewResourceDropdown, LocalStorageSync, - GitlabExperiment, WorkItemDrawer, }, directives: { @@ -1060,18 +1058,13 @@ export default { :export-csv-path-with-query="exportCsvPathWithQuery" :show-csv-buttons="showCsvButtons" :show-new-issue-dropdown="showNewIssueDropdown" - :show-issuable-by-email="showIssuableByEmail" /> - <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" - 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> + <issuable-by-email + v-if="showIssuableByEmail" + 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" + /> </div> </template> diff --git a/app/assets/stylesheets/page_bundles/issuable_list.scss b/app/assets/stylesheets/page_bundles/issuable_list.scss index 4f932a9a20f3b..c2955a8a2562f 100644 --- a/app/assets/stylesheets/page_bundles/issuable_list.scss +++ b/app/assets/stylesheets/page_bundles/issuable_list.scss @@ -106,10 +106,3 @@ } } } - -.gl-empty-state { - .video-container { - aspect-ratio: 16/9; - max-width: 350px; - } -} diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml index 4a55d908eb0dd..b17c243967248 100644 --- a/app/views/shared/empty_states/_merge_requests.html.haml +++ b/app/views/shared/empty_states/_merge_requests.html.haml @@ -35,4 +35,16 @@ title: _("There are no closed merge requests")) - else - = render_if_exists 'shared/empty_states/merge_requests_without_filters', button_path: button_path + = 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| + + - c.with_description do + = _("Interested parties can even contribute by pushing commits if they want to.") + - if button_path + .gl-mt-5= link_button_to button_text, button_path, + title: button_text, + id: 'new_merge_request_link', + variant: :confirm, + data: { testid: "new-merge-request-button", **tracking_data } + diff --git a/app/views/shared/empty_states/_merge_requests_without_filters.html.haml b/app/views/shared/empty_states/_merge_requests_without_filters.html.haml deleted file mode 100644 index 66cd2f6719d79..0000000000000 --- a/app/views/shared/empty_states/_merge_requests_without_filters.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -- 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| - - - c.with_description do - = _('Interested parties can even contribute by pushing commits if they want to.') - - if button_path - .gl-mt-5 - = link_button_to button_text, button_path, - title: button_text, - id: 'new_merge_request_link', - variant: :confirm, - data: { testid: 'new-merge-request-button', **project_tracking_data } diff --git a/ee/app/controllers/concerns/iframe_youtube_video_csp.rb b/ee/app/controllers/concerns/iframe_youtube_video_csp.rb deleted file mode 100644 index 85985d79cbfeb..0000000000000 --- a/ee/app/controllers/concerns/iframe_youtube_video_csp.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -module IframeYoutubeVideoCSP - extend ActiveSupport::Concern - - included do - content_security_policy do |policy| - next if policy.directives.blank? - - # youtube-nocookie.com is needed for embeded video for issues_mrs_empty_state experiment - # https://gitlab.com/gitlab-org/gitlab/-/issues/436480 - frame_src_values = Array.wrap(policy.directives['frame-src']) | ['https://www.youtube-nocookie.com'] - policy.frame_src(*frame_src_values) - end - end -end diff --git a/ee/app/controllers/ee/projects/issues_controller.rb b/ee/app/controllers/ee/projects/issues_controller.rb index 9c4771220bb7c..341b707cfcc45 100644 --- a/ee/app/controllers/ee/projects/issues_controller.rb +++ b/ee/app/controllers/ee/projects/issues_controller.rb @@ -12,7 +12,6 @@ module IssuesController include DescriptionDiffActions include GeoInstrumentation include GitlabSubscriptions::SeatCountAlert - include IframeYoutubeVideoCSP before_action :disable_query_limiting_ee, only: [:update] before_action only: [:new, :create] do @@ -34,13 +33,6 @@ module IssuesController before_action :redirect_if_test_case, only: [:show] before_action only: :index do - experiment(:issues_mrs_empty_state, - type: :experiment, - user: current_user, - project: project, - namespace: project&.namespace - ).publish - push_force_frontend_feature_flag(:okrs_mvc, project&.okrs_mvc_feature_flag_enabled?) push_licensed_feature(:okrs, project) end diff --git a/ee/app/controllers/ee/projects/merge_requests_controller.rb b/ee/app/controllers/ee/projects/merge_requests_controller.rb index 690c6f141d049..dc9a6885e271c 100644 --- a/ee/app/controllers/ee/projects/merge_requests_controller.rb +++ b/ee/app/controllers/ee/projects/merge_requests_controller.rb @@ -8,7 +8,6 @@ module MergeRequestsController prepended do include DescriptionDiffActions include GeoInstrumentation - include IframeYoutubeVideoCSP before_action only: [:show] do push_frontend_feature_flag(:merge_trains_skip_train, @project) diff --git a/ee/app/experiments/issues_mrs_empty_state_experiment.rb b/ee/app/experiments/issues_mrs_empty_state_experiment.rb deleted file mode 100644 index 11c3e2098e80e..0000000000000 --- a/ee/app/experiments/issues_mrs_empty_state_experiment.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -class IssuesMrsEmptyStateExperiment < ApplicationExperiment - EXCLUDE_USERS_OLDER_THAN = Date.new(2024, 4, 17) - - control - variant(:candidate) - - exclude :signed_out_and_old_users, :empty_project_and_paid_plans - - private - - def control_behavior; end - def candidate_behavior; end - - def signed_out_and_old_users - return true unless context.user - - context.user.created_at < EXCLUDE_USERS_OLDER_THAN - end - - def empty_project_and_paid_plans - return true unless context.project - - context.project.root_ancestor.paid? && !context.project.root_ancestor.trial? - end -end diff --git a/ee/app/helpers/ee/merge_requests_helper.rb b/ee/app/helpers/ee/merge_requests_helper.rb index 8dd89c2f32943..6fddb65c94480 100644 --- a/ee/app/helpers/ee/merge_requests_helper.rb +++ b/ee/app/helpers/ee/merge_requests_helper.rb @@ -44,18 +44,6 @@ def review_bar_data(merge_request, user) super.merge({ can_summarize: Ability.allowed?(user, :summarize_draft_code_review, merge_request).to_s }) end - def show_video_component?(project) - experiment(:issues_mrs_empty_state, - type: :experiment, - user: current_user, - project: project, - namespace: project&.namespace - ) do |e| - e.control { false } - e.candidate { true } - end.run - end - override :identity_verification_alert_data def identity_verification_alert_data(merge_request) { 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 deleted file mode 100644 index 6b2e180fda3d2..0000000000000 --- a/ee/app/views/shared/empty_states/_merge_requests_without_filters.html.haml +++ /dev/null @@ -1,41 +0,0 @@ -- 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', - 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/ee/config/feature_flags/experiment/issues_mrs_empty_state.yml b/ee/config/feature_flags/experiment/issues_mrs_empty_state.yml deleted file mode 100644 index 117bee5c63351..0000000000000 --- a/ee/config/feature_flags/experiment/issues_mrs_empty_state.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: issues_mrs_empty_state -feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/436480 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144318 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/441647 -milestone: '16.11' -group: group::activation -type: experiment -default_enabled: false diff --git a/ee/spec/experiments/issues_mrs_empty_state_experiment_spec.rb b/ee/spec/experiments/issues_mrs_empty_state_experiment_spec.rb deleted file mode 100644 index 0a006b05fcef2..0000000000000 --- a/ee/spec/experiments/issues_mrs_empty_state_experiment_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe IssuesMrsEmptyStateExperiment, :experiment, :saas, feature_category: :activation do - let_it_be(:old_user) { build_stubbed(:user, created_at: Date.new(2024, 4, 16)) } - let_it_be(:free_project) { create(:project) } - let_it_be(:ultimate_project) { create(:project, :in_group) } - - let_it_be(:new_user) do - build_stubbed(:user, created_at: IssuesMrsEmptyStateExperiment::EXCLUDE_USERS_OLDER_THAN) - end - - let_it_be(:subscription) do - create(:gitlab_subscription, :ultimate, namespace: ultimate_project.group) - end - - shared_examples 'excluded_users' do - it 'excludes signed out users, old users, empty projects and paid plans' do - expect(experiment(:issues_mrs_empty_state)).to exclude(user: nil, project: free_project) - expect(experiment(:issues_mrs_empty_state)).to exclude(user: old_user, project: free_project) - expect(experiment(:issues_mrs_empty_state)).to exclude(user: new_user, project: nil) - expect(experiment(:issues_mrs_empty_state)).to exclude(user: new_user, project: ultimate_project) - expect(experiment(:issues_mrs_empty_state)).not_to exclude(user: new_user, project: free_project) - end - end - - context 'with control experience' do - before do - stub_experiments(issues_mrs_empty_state: :control) - end - - it 'registers control behavior' do - expect(experiment(:issues_mrs_empty_state)).to register_behavior(:control).with(nil) - expect { experiment(:issues_mrs_empty_state, user: new_user, project: free_project).run }.not_to raise_error - end - - it_behaves_like 'excluded_users' - end - - context 'with candidate experience' do - before do - stub_experiments(issues_mrs_empty_state: :candidate) - end - - it 'registers candidate behavior' do - expect(experiment(:issues_mrs_empty_state)).to register_behavior(:candidate).with(nil) - expect { experiment(:issues_mrs_empty_state, user: new_user, project: free_project).run }.not_to raise_error - end - - it_behaves_like 'excluded_users' - end -end diff --git a/ee/spec/features/projects/issues/iframe_youtube_video_csp_spec.rb b/ee/spec/features/projects/issues/iframe_youtube_video_csp_spec.rb deleted file mode 100644 index 2a19997748f87..0000000000000 --- a/ee/spec/features/projects/issues/iframe_youtube_video_csp_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Youtube iframe content security policy', feature_category: :activation do - include ContentSecurityPolicyHelpers - - let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, developers: user) } - - subject(:csp_header) { response_headers['Content-Security-Policy'] } - - it 'includes content security policy headers' do - sign_in(user) - - visit project_issues_path(project) - - expect(find_csp_directive('frame-src', header: csp_header)).to include( - 'https://www.youtube-nocookie.com' - ) - end -end diff --git a/ee/spec/helpers/ee/merge_requests_helper_spec.rb b/ee/spec/helpers/ee/merge_requests_helper_spec.rb index 3e5f4264b407c..3c955c5ba6cc6 100644 --- a/ee/spec/helpers/ee/merge_requests_helper_spec.rb +++ b/ee/spec/helpers/ee/merge_requests_helper_spec.rb @@ -128,64 +128,6 @@ end end - describe '#show_video_component?' do - before do - allow(helper).to receive(:current_user).and_return(nil) - end - - context 'when project is nil' do - subject do - helper.show_video_component?(nil) - end - - it 'returns false' do - expect(subject).to eq(false) - end - end - - context 'when project is set' do - let_it_be(:project) { build_stubbed(:project) } - - subject do - helper.show_video_component?(project) - end - - context 'when user is not signed in' do - it 'returns false' do - expect(subject).to eq(false) - end - end - - context 'when user is signed in' do - before do - allow(helper).to receive(:current_user).and_return( - build_stubbed(:user, created_at: IssuesMrsEmptyStateExperiment::EXCLUDE_USERS_OLDER_THAN) - ) - end - - describe 'when control behavior' do - before do - stub_experiments(issues_mrs_empty_state: :control) - end - - it 'returns false' do - expect(subject).to eq(false) - end - end - - describe 'when candidate behavior' do - before do - stub_experiments(issues_mrs_empty_state: :candidate) - end - - it 'returns true' do - expect(subject).to eq(true) - end - end - end - end - end - describe '#identity_verification_alert_data' do let_it_be(:current_user) { build_stubbed(:user) } let(:author) { current_user } diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3c7f47b212199..b0e8f75cfeeaa 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1953,9 +1953,6 @@ msgstr "" msgid "A member of the abuse team will review your report as soon as possible." msgstr "" -msgid "A merge request (MR) is a proposal to incorporate changes from a source branch to a target branch." -msgstr "" - msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details" msgstr "" @@ -15443,9 +15440,6 @@ msgstr "" msgid "Create a new issue" msgstr "" -msgid "Create a new merge request" -msgstr "" - msgid "Create a new project" msgstr "" @@ -19864,9 +19858,6 @@ msgstr "" msgid "Email a new %{name} to this project" msgstr "" -msgid "Email a new issue" -msgstr "" - msgid "Email address copied" msgstr "" @@ -20029,9 +20020,6 @@ msgstr "" msgid "Enable Invisible Captcha during sign up" msgstr "" -msgid "Enable Jira integration" -msgstr "" - msgid "Enable Kroki" msgstr "" @@ -27040,9 +27028,6 @@ msgstr "" msgid "Import and export settings" msgstr "" -msgid "Import existing issues" -msgstr "" - msgid "Import from" msgstr "" @@ -30788,9 +30773,6 @@ msgstr "" msgid "Learn more about groups." msgstr "" -msgid "Learn more about issues" -msgstr "" - msgid "Learn more about issues." msgstr "" @@ -30806,9 +30788,6 @@ msgstr "" msgid "Learn more about max seats used" msgstr "" -msgid "Learn more about merge requests" -msgstr "" - msgid "Learn more about seats owed" msgstr "" @@ -43514,9 +43493,6 @@ msgstr "" msgid "Read more about GitLab at %{link_to_promo}." msgstr "" -msgid "Read our documentation" -msgstr "" - msgid "Read the documentation before applying changes." msgstr "" @@ -54255,9 +54231,6 @@ msgstr "" msgid "This feature is not enabled yet." msgstr "" -msgid "This feature is only available on paid plans." -msgstr "" - msgid "This feature requires local storage to be enabled" msgstr "" @@ -59712,9 +59685,6 @@ msgstr "" msgid "When using the %{code_open}ssh://%{code_close} protocol, please use the following format: %{code_open}ssh://username@example.com/group/project.git%{code_close}." msgstr "" -msgid "When you open a merge request, you can visualize and collaborate on the changes before merge." -msgstr "" - msgid "When you transfer your project to a group, you can easily manage multiple projects, view usage quotas for storage, compute minutes, and users, and start a trial or upgrade to a paid tier." msgstr "" @@ -60052,9 +60022,6 @@ msgstr "" msgid "With custom notification levels you receive notifications for the same events as in the Participate level, with additional selected events. For more information, see %{notificationLinkStart}notification emails%{notificationLinkEnd}." msgstr "" -msgid "With issues you can discuss the implementation of an idea, track tasks and work status, elaborate on code implementations, and accept feature proposals, questions, support requests, or bug reports." -msgstr "" - msgid "With requirements, you can set criteria to check your products against." msgstr "" diff --git a/qa/qa/page/merge_request/index.rb b/qa/qa/page/merge_request/index.rb index 5c82a964e8946..14623fe68a272 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/_merge_requests_without_filters.html.haml' do + view 'app/views/shared/empty_states/_merge_requests.html.haml' do element 'new-merge-request-button' end 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 3d1f00d624bcd..3e94913dae065 100644 --- a/spec/frontend/issuable/components/csv_import_export_buttons_spec.js +++ b/spec/frontend/issuable/components/csv_import_export_buttons_spec.js @@ -141,62 +141,5 @@ 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/issuable/components/issuable_by_email_spec.js b/spec/frontend/issuable/components/issuable_by_email_spec.js index 2d9b0b4d04762..4cc5775b54e77 100644 --- a/spec/frontend/issuable/components/issuable_by_email_spec.js +++ b/spec/frontend/issuable/components/issuable_by_email_spec.js @@ -16,7 +16,7 @@ describe('IssuableByEmail', () => { let mockAxios; let glModalDirective; - function createComponent(injectedProperties = {}, props = {}) { + function createComponent(injectedProperties = {}) { glModalDirective = jest.fn(); return extendedWrapper( @@ -39,7 +39,6 @@ describe('IssuableByEmail', () => { show: mockToastShow, }, }, - propsData: props, provide: { issuableType: 'issue', initialEmail, @@ -86,20 +85,6 @@ describe('IssuableByEmail', () => { expect(glModalDirective).toHaveBeenCalled(); }); - - describe('when passing variant and button text', () => { - it('renders correct button', () => { - const variant = 'default'; - const text = 'Email a new issue'; - - wrapper = createComponent({}, { variant, text }); - - const button = findButton(); - - expect(button.attributes('variant')).toBe(variant); - expect(button.text()).toBe(text); - }); - }); }); describe('modal', () => { 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 deleted file mode 100644 index 5251906f21fc6..0000000000000 --- a/spec/frontend/issues/list/components/empty_state_without_any_issues_experiment_spec.js +++ /dev/null @@ -1,241 +0,0 @@ -import { mountExtended } from 'helpers/vue_test_utils_helper'; -import IssuableByEmail from '~/issuable/components/issuable_by_email.vue'; -import EmptyStateWithoutAnyIssuesExperiment from '~/issues/list/components/empty_state_without_any_issues_experiment.vue'; - -describe('EmptyStateWithoutAnyIssuesExperiment component', () => { - let wrapper; - - const defaultProps = { - showCsvButtons: true, - showIssuableByEmail: true, - }; - - const defaultProvide = { - newIssuePath: 'new/issue/path', - showNewIssueLink: true, - showImportButton: true, - canEdit: true, - projectImportJiraPath: 'project/import/jira/path', - }; - - const findCreateAnIssueVideo = () => wrapper.findByTestId('create-an-issue-iframe-video'); - const findNewIssueButton = () => wrapper.findByTestId('empty-state-new-issue-btn'); - 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, { - propsData: { - ...defaultProps, - ...props, - }, - provide: { - ...defaultProvide, - ...provide, - }, - }); - }; - - it('renders empty state', () => { - mountComponent(); - - expect(findCreateAnIssueVideo().exists()).toBe(true); - - expect(wrapper.find('h1').text()).toBe( - 'Use issues to collaborate on ideas, solve problems, and plan work', - ); - - const text = wrapper.text(); - - expect(text).toContain( - 'With issues you can discuss the implementation of an idea, track tasks and work status, elaborate on code implementations, and accept feature proposals, questions, support requests, or bug reports.', - ); - - expect(text).toContain('Learn more about issues'); - expect(text).toContain('Read our documentation'); - expect(text).toContain('Enable Jira integration'); - expect(text).toContain('This feature is only available on paid plans.'); - }); - - describe('actions', () => { - describe('"New issue" button', () => { - describe('when can show the button', () => { - it('renders', () => { - mountComponent(); - - const newIssueButton = findNewIssueButton(); - - expect(newIssueButton.attributes('href')).toBe(defaultProvide.newIssuePath); - expect(newIssueButton.props('variant')).toBe('confirm'); - expect(newIssueButton.text()).toBe('Create a new issue'); - }); - }); - - describe('when cannot show the button', () => { - it('does not render', () => { - mountComponent({ provide: { showNewIssueLink: false } }); - - expect(findNewIssueButton().exists()).toBe(false); - }); - }); - }); - - describe('"Email a new issue" button', () => { - describe('when can show the button', () => { - it('renders', () => { - mountComponent(); - - const newIssueButton = findIssuableByEmail(); - - expect(newIssueButton.props('variant')).toBe('default'); - expect(newIssueButton.text()).toBe('Email a new issue'); - }); - }); - - describe('when cannot show the button', () => { - it('does not render', () => { - mountComponent({ props: { showIssuableByEmail: false } }); - - expect(findIssuableByEmail().exists()).toBe(false); - }); - }); - }); - - describe('Import buttons', () => { - describe('when can show csv buttons', () => { - describe('when can show import buttons', () => { - describe('when cannot edit', () => { - it('renders import CSV button and does not render from Jira button', () => { - mountComponent({ provide: { canEdit: false } }); - - const csvImportButton = findCsvImportButton(); - - expect(csvImportButton.exists()).toBe(true); - expect(csvImportButton.text()).toBe('Import CSV'); - - expect(findImportFromJiraButton().exists()).toBe(false); - }); - }); - - describe('when can edit', () => { - it('renders import from Jira button', () => { - mountComponent(); - - const importFromJiraButton = findImportFromJiraButton(); - - expect(importFromJiraButton.exists()).toBe(true); - expect(importFromJiraButton.text()).toBe('Import from Jira'); - - expect(importFromJiraButton.attributes('href')).toBe( - defaultProvide.projectImportJiraPath, - ); - - expect(findCsvImportButton().exists()).toBe(true); - }); - }); - }); - - describe('when cannot show import buttons', () => { - it('does not render import buttons', () => { - mountComponent({ provide: { showImportButton: false } }); - - expect(findCsvImportButton().exists()).toBe(false); - expect(findImportFromJiraButton().exists()).toBe(false); - }); - }); - }); - - describe('when cannot show csv buttons', () => { - it('does not render import buttons', () => { - mountComponent({ props: { showCsvButtons: false } }); - - expect(findCsvImportButton().exists()).toBe(false); - expect(findImportFromJiraButton().exists()).toBe(false); - }); - }); - }); - }); - - 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 f0790d83f694c..43f8b76f3d981 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 @@ -1,11 +1,8 @@ import { GlDisclosureDropdown, GlEmptyState, GlLink } from '@gitlab/ui'; import { mountExtended } from 'helpers/vue_test_utils_helper'; -import { stubExperiments } from 'helpers/experimentation_helper'; import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue'; import EmptyStateWithoutAnyIssues from '~/issues/list/components/empty_state_without_any_issues.vue'; -import EmptyStateWithoutAnyIssuesExperiment from '~/issues/list/components/empty_state_without_any_issues_experiment.vue'; import NewResourceDropdown from '~/vue_shared/components/new_resource_dropdown/new_resource_dropdown.vue'; -import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; describe('EmptyStateWithoutAnyIssues component', () => { let wrapper; @@ -27,7 +24,6 @@ describe('EmptyStateWithoutAnyIssues component', () => { 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); @@ -51,7 +47,6 @@ describe('EmptyStateWithoutAnyIssues component', () => { ...provide, }, stubs: { - GitlabExperiment, NewResourceDropdown: true, }, }); @@ -177,89 +172,6 @@ describe('EmptyStateWithoutAnyIssues component', () => { }); }); }); - - describe('tracking', () => { - const experimentTracking = { 'data-track-experiment': 'issues_mrs_empty_state' }; - - const emptyStateBlockTracking = { - 'data-track-action': 'render', - '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', () => { @@ -282,21 +194,6 @@ describe('EmptyStateWithoutAnyIssues component', () => { ); }); }); - - describe('when issues_mrs_empty_state candidate experiment', () => { - beforeEach(() => { - stubExperiments({ issues_mrs_empty_state: 'candidate' }); - }); - - it('renders EmptyStateWithoutAnyIssuesExperiment', () => { - mountComponent(); - - expect(wrapper.findComponent(EmptyStateWithoutAnyIssuesExperiment).props()).toEqual({ - showCsvButtons: false, - showIssuableByEmail: false, - }); - }); - }); }); describe('when signed out', () => { diff --git a/spec/frontend/issues/list/components/gl_card_empty_state_experiment_spec.js b/spec/frontend/issues/list/components/gl_card_empty_state_experiment_spec.js deleted file mode 100644 index 4b7fd0e8fbbdd..0000000000000 --- a/spec/frontend/issues/list/components/gl_card_empty_state_experiment_spec.js +++ /dev/null @@ -1,35 +0,0 @@ -import { GlCard, GlIcon } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import GlCardEmptyStateExperiment from '~/issues/list/components/gl_card_empty_state_experiment.vue'; - -describe('GlCardEmptyStateExperiment component', () => { - let wrapper; - - const propsData = { - icon: 'download', - }; - - const findGlCard = () => wrapper.findComponent(GlCard); - const findGlIcon = () => wrapper.findComponent(GlIcon); - const findCardHeader = () => findGlCard().find('p'); - const findCardBody = () => findGlCard().find('.body-content'); - - const mountComponent = () => { - wrapper = shallowMount(GlCardEmptyStateExperiment, { - propsData, - slots: { - header: 'Header content', - body: '<div class="body-content">Body content</div>', - }, - }); - }; - - it('renders empty state experiment card', () => { - mountComponent(); - - expect(findGlCard().exists()).toBe(true); - expect(findGlIcon().props('name')).toBe(propsData.icon); - expect(findCardHeader().text()).toBe('Header content'); - expect(findCardBody().text()).toBe('Body content'); - }); -}); 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 c4e86e3e711aa..628fd78b4e6f7 100644 --- a/spec/frontend/issues/list/components/issues_list_app_spec.js +++ b/spec/frontend/issues/list/components/issues_list_app_spec.js @@ -87,9 +87,6 @@ import { mockMilestone, } from 'jest/work_items/mock_data'; -import { stubExperiments } from 'helpers/experimentation_helper'; -import GitlabExperiment from '~/experimentation/components/gitlab_experiment.vue'; - import('~/issuable'); import('~/users_select'); @@ -573,22 +570,6 @@ describe('CE IssuesListApp component', () => { 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' }); - }); - - it('does not render IssuableByEmail', () => { - wrapper = mountComponent({ - provide: { initialEmail: true, canCreateIssue: true }, - stubs: { GitlabExperiment }, - }); - - expect(findIssuableByEmail().exists()).toBe(false); }); }); }); -- GitLab