From a3dd2aac62f4d17f57fcc06d319e057e4573c595 Mon Sep 17 00:00:00 2001
From: Thomas Randolph <trandolph@gitlab.com>
Date: Fri, 19 Apr 2024 07:49:32 +0000
Subject: [PATCH] Migrate deprecated dropdown in pipeline deployment widget

Migrates deprecated GlDropdown to GlCollapsibleListbox.

Changelog: fixed
---
 .../deployment/deployment_view_button.vue     | 66 ++++++++-----------
 .../deployment/deployment_view_button_spec.js | 22 ++++---
 2 files changed, 40 insertions(+), 48 deletions(-)

diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
index f4029c392251..cbb1ed4583d5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue
@@ -1,12 +1,5 @@
 <script>
-import {
-  GlButtonGroup,
-  GlDropdown,
-  GlDropdownItem,
-  GlIcon,
-  GlLink,
-  GlSearchBoxByType,
-} from '@gitlab/ui';
+import { GlButtonGroup, GlCollapsibleListbox, GlLink } from '@gitlab/ui';
 import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
 import ReviewAppLink from '../review_app_link.vue';
 
@@ -14,11 +7,8 @@ export default {
   name: 'DeploymentViewButton',
   components: {
     GlButtonGroup,
-    GlDropdown,
-    GlDropdownItem,
-    GlIcon,
+    GlCollapsibleListbox,
     GlLink,
-    GlSearchBoxByType,
     ReviewAppLink,
   },
   directives: {
@@ -48,7 +38,14 @@ export default {
       return this.deployment.changes && this.deployment.changes.length > 1;
     },
     filteredChanges() {
-      return this.deployment?.changes?.filter((change) => change.path.includes(this.searchTerm));
+      return this.deployment?.changes
+        ?.filter((change) => change.path.includes(this.searchTerm))
+        .map((change) => ({ value: change.external_url, text: change.path }));
+    },
+  },
+  methods: {
+    search(searchTerm) {
+      this.searchTerm = searchTerm;
     },
   },
 };
@@ -62,33 +59,24 @@ export default {
         size="small"
         css-class="deploy-link js-deploy-url gl-display-inline"
       />
-      <gl-dropdown toggle-class="gl-px-2!" size="small" class="js-mr-wigdet-deployment-dropdown">
-        <template #button-content>
-          <gl-icon
-            class="dropdown-chevron gl-mx-0!"
-            name="chevron-down"
-            data-testid="mr-wigdet-deployment-dropdown-icon"
-          />
-        </template>
-        <gl-search-box-by-type v-model.trim="searchTerm" v-autofocusonshow autofocus />
-        <gl-dropdown-item
-          v-for="change in filteredChanges"
-          :key="change.path"
-          class="js-filtered-dropdown-result"
-        >
-          <gl-link
-            :href="change.external_url"
-            target="_blank"
-            rel="noopener noreferrer nofollow"
-            class="js-deploy-url-menu-item menu-item"
-          >
-            <strong class="str-truncated-100 gl-mb-0 gl-display-block">{{ change.path }}</strong>
-            <p class="text-secondary str-truncated-100 gl-mb-0 d-block">
-              {{ change.external_url }}
-            </p>
+      <gl-collapsible-listbox
+        :items="filteredChanges"
+        size="small"
+        placement="right"
+        searchable
+        @search="search"
+      >
+        <template #list-item="{ item }">
+          <gl-link :href="item.value" target="_blank" rel="noopener noreferrer nofollow">
+            <div>
+              <strong class="gl-text-truncate gl-mb-0 gl-display-block">{{ item.text }}</strong>
+              <p class="gl-text-secondary gl-text-truncate gl-mb-0 gl-display-block">
+                {{ item.value }}
+              </p>
+            </div>
           </gl-link>
-        </gl-dropdown-item>
-      </gl-dropdown>
+        </template>
+      </gl-collapsible-listbox>
     </gl-button-group>
     <review-app-link
       v-else
diff --git a/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
index 72cfd5dd29f0..fbd163f1652f 100644
--- a/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
+++ b/spec/frontend/vue_merge_request_widget/deployment/deployment_view_button_spec.js
@@ -1,4 +1,4 @@
-import { GlDropdown, GlLink } from '@gitlab/ui';
+import { GlCollapsibleListbox, GlLink } from '@gitlab/ui';
 import { mountExtended } from 'helpers/vue_test_utils_helper';
 import DeploymentViewButton from '~/vue_merge_request_widget/components/deployment/deployment_view_button.vue';
 import ReviewAppLink from '~/vue_merge_request_widget/components/review_app_link.vue';
@@ -28,9 +28,7 @@ describe('Deployment View App button', () => {
   });
 
   const findReviewAppLink = () => wrapper.findComponent(ReviewAppLink);
-  const findMrWigdetDeploymentDropdown = () => wrapper.findComponent(GlDropdown);
-  const findMrWigdetDeploymentDropdownIcon = () =>
-    wrapper.findByTestId('mr-wigdet-deployment-dropdown-icon');
+  const findMrWidgetDeploymentDropdown = () => wrapper.findComponent(GlCollapsibleListbox);
   const findDeployUrlMenuItems = () => wrapper.findAllComponents(GlLink);
 
   describe('text', () => {
@@ -50,7 +48,7 @@ describe('Deployment View App button', () => {
     });
 
     it('renders the link to the review app without dropdown', () => {
-      expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
+      expect(findMrWidgetDeploymentDropdown().exists()).toBe(false);
     });
   });
 
@@ -65,8 +63,7 @@ describe('Deployment View App button', () => {
     });
 
     it('renders the link to the review app without dropdown', () => {
-      expect(findMrWigdetDeploymentDropdown().exists()).toBe(false);
-      expect(findMrWigdetDeploymentDropdownIcon().exists()).toBe(false);
+      expect(findMrWidgetDeploymentDropdown().exists()).toBe(false);
     });
 
     it('renders the link to the review app linked to to the first change', () => {
@@ -87,8 +84,15 @@ describe('Deployment View App button', () => {
     });
 
     it('renders the link to the review app with dropdown', () => {
-      expect(findMrWigdetDeploymentDropdown().exists()).toBe(true);
-      expect(findMrWigdetDeploymentDropdownIcon().exists()).toBe(true);
+      const dropdown = findMrWidgetDeploymentDropdown();
+      const thirdChangeUrl = deploymentMockData.changes[2].external_url;
+
+      expect(dropdown.exists()).toBe(true);
+
+      const links = dropdown.findAll('a');
+
+      expect(links.length).toBe(3);
+      expect(links.at(2).attributes('href')).toBe(thirdChangeUrl);
     });
 
     it('renders all the links to the review apps', () => {
-- 
GitLab