From fbb15a7adc045ff16463386875f6634bbc758eb5 Mon Sep 17 00:00:00 2001 From: Thomas Randolph Date: Wed, 12 Nov 2025 17:13:51 -0700 Subject: [PATCH 1/5] Add component to manually override the disclosure item slot --- .../rapid_diffs/adapters/options_menu.js | 37 ++++++++++++------- .../diff_file_options_menu_item.vue | 25 +++++++++++++ .../rapid_diffs/diff_file_header_component.rb | 2 +- 3 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue diff --git a/app/assets/javascripts/rapid_diffs/adapters/options_menu.js b/app/assets/javascripts/rapid_diffs/adapters/options_menu.js index f69a96b82e757a..3dc1adbd58cf4d 100644 --- a/app/assets/javascripts/rapid_diffs/adapters/options_menu.js +++ b/app/assets/javascripts/rapid_diffs/adapters/options_menu.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import { GlDisclosureDropdown } from '@gitlab/ui'; +import DiffFileOptionsMenuItem from '~/rapid_diffs/app/components/diff_file_options_menu_item.vue'; import { s__ } from '~/locale'; function getMenuItems(container) { @@ -26,21 +27,29 @@ export const optionsMenuAdapter = { }); }, render(h) { - return h(GlDisclosureDropdown, { - props: { - icon: 'ellipsis_v', - startOpened: true, - noCaret: true, - category: 'tertiary', - size: 'small', - items, - toggleText: s__('RapidDiffs|Show options'), - textSrOnly: true, + return h( + GlDisclosureDropdown, + { + props: { + icon: 'ellipsis_v', + startOpened: true, + noCaret: true, + category: 'tertiary', + size: 'small', + toggleText: s__('RapidDiffs|Show options'), + textSrOnly: true, + }, + attrs: { + 'data-options-toggle': true, + }, }, - attrs: { - 'data-options-toggle': true, - }, - }); + items.map((item) => + h(DiffFileOptionsMenuItem, { + props: { item }, + key: item.text, + }), + ), + ); }, }); }, diff --git a/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue new file mode 100644 index 00000000000000..75d3d98203a565 --- /dev/null +++ b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue @@ -0,0 +1,25 @@ + + + \ No newline at end of file diff --git a/app/components/rapid_diffs/diff_file_header_component.rb b/app/components/rapid_diffs/diff_file_header_component.rb index b69da0abf14586..6dff61ba33d01f 100644 --- a/app/components/rapid_diffs/diff_file_header_component.rb +++ b/app/components/rapid_diffs/diff_file_header_component.rb @@ -85,7 +85,7 @@ def view_file_menu_item { text: helpers.safe_format( s_('RapidDiffs|View file at %{commitId}'), - commitId: @diff_file.content_sha[0..7] + commitId: helpers.tag.code(@diff_file.content_sha[0..7]) ), href: view_path, extraAttrs: { target: '_blank' }, -- GitLab From 2eaa15cf8cfc8e20f3c5a059ce30d3bf7e8dfb84 Mon Sep 17 00:00:00 2001 From: Thomas Randolph Date: Wed, 12 Nov 2025 17:41:13 -0700 Subject: [PATCH 2/5] Test that the "View file at [SHA]" menu item uses a code block --- .../components/rapid_diffs/diff_file_header_component_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/components/rapid_diffs/diff_file_header_component_spec.rb b/spec/components/rapid_diffs/diff_file_header_component_spec.rb index 8ad831bcb6242b..35b59281938bfc 100644 --- a/spec/components/rapid_diffs/diff_file_header_component_spec.rb +++ b/spec/components/rapid_diffs/diff_file_header_component_spec.rb @@ -155,12 +155,12 @@ allow(diff_file).to receive(:content_sha).and_return(content_sha) end - it 'always renders the "View file at [SHA]" menu item' do + it 'always renders the "View file at [SHA]" menu item (in a code tag)' do render_component options_menu_items = Gitlab::Json.parse(page.find('script', visible: false).text) - expect(options_menu_items.first['text']).to eq('View file at abc123') + expect(options_menu_items.first['text']).to eq('View file at abc123') end it 'renders additional menu items with respective order' do -- GitLab From c849739eacef0d03f4e9c4d05b5fe9f3857fa143 Mon Sep 17 00:00:00 2001 From: Thomas Randolph Date: Wed, 12 Nov 2025 17:43:52 -0700 Subject: [PATCH 3/5] Test the new Vue component for rendering arbitrary HTML in the menu --- .../diff_file_options_menu_item_spec.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js diff --git a/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js b/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js new file mode 100644 index 00000000000000..d00712cee75eb3 --- /dev/null +++ b/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js @@ -0,0 +1,32 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlDisclosureDropdownItem } from '@gitlab/ui'; +import DiffFileOptionsMenuItem from '~/rapid_diffs/app/components/diff_file_options_menu_item.vue'; + +describe('DiffFileOptionsMenuItem', () => { + let wrapper; + + const createComponent = (item = {}) => { + wrapper = shallowMount(DiffFileOptionsMenuItem, { + propsData: { item }, + }); + }; + + const findDropdownItem = () => wrapper.findComponent(GlDisclosureDropdownItem); + + it('passes the item prop to GlDisclosureDropdownItem', () => { + const item = { text: 'Test item' }; + createComponent(item); + + expect(findDropdownItem().props('item')).toBe(item); + }); + + it('renders HTML content in the list-item slot', () => { + const item = { text: 'View file at abc1234' }; + createComponent(item); + + const slotContent = findDropdownItem().find('span'); + + expect(slotContent.exists()).toBe(true); + expect(slotContent.html()).toContain('abc1234'); + }); +}); \ No newline at end of file -- GitLab From a59d124e71b014efd969aa63fe2a05e31bd33094 Mon Sep 17 00:00:00 2001 From: Thomas Randolph Date: Wed, 12 Nov 2025 18:04:13 -0700 Subject: [PATCH 4/5] Add EOF newlines --- .../rapid_diffs/app/components/diff_file_options_menu_item.vue | 2 +- .../app/components/diff_file_options_menu_item_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue index 75d3d98203a565..d15e40eb96c02d 100644 --- a/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue +++ b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue @@ -22,4 +22,4 @@ export default { - \ No newline at end of file + diff --git a/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js b/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js index d00712cee75eb3..fbb79eee239223 100644 --- a/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js +++ b/spec/frontend/rapid_diffs/app/components/diff_file_options_menu_item_spec.js @@ -29,4 +29,4 @@ describe('DiffFileOptionsMenuItem', () => { expect(slotContent.exists()).toBe(true); expect(slotContent.html()).toContain('abc1234'); }); -}); \ No newline at end of file +}); -- GitLab From 30c4a3a9039246659eeafc60c140f1b4bff75317 Mon Sep 17 00:00:00 2001 From: Thomas Randolph Date: Thu, 13 Nov 2025 15:08:47 -0700 Subject: [PATCH 5/5] Use v-safe-html --- .../app/components/diff_file_options_menu_item.vue | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue index d15e40eb96c02d..cb0050ae0e3838 100644 --- a/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue +++ b/app/assets/javascripts/rapid_diffs/app/components/diff_file_options_menu_item.vue @@ -1,11 +1,15 @@