From 88404ad579fa6ca07f5a2e8b860bcb9516477421 Mon Sep 17 00:00:00 2001 From: Stanislav Lashmanov Date: Thu, 27 Nov 2025 17:30:43 +0400 Subject: [PATCH 1/4] Migrate system_note.vue component in Rapid Diffs discussions --- .../app/discussions/discussion_notes.vue | 5 +- .../app/discussions/note_author.vue | 35 +++++++++ .../app/discussions/note_header.vue | 17 +---- .../app/discussions/system_note.vue | 62 ++++++++++++++++ .../app/discussions/discussion_notes_spec.js | 12 ---- .../app/discussions/note_author_spec.js | 72 +++++++++++++++++++ .../app/discussions/note_header_spec.js | 33 +-------- .../app/discussions/system_note_spec.js | 31 ++++++++ 8 files changed, 208 insertions(+), 59 deletions(-) create mode 100644 app/assets/javascripts/rapid_diffs/app/discussions/note_author.vue create mode 100644 app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue create mode 100644 spec/frontend/rapid_diffs/app/discussions/note_author_spec.js create mode 100644 spec/frontend/rapid_diffs/app/discussions/system_note_spec.js diff --git a/app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue b/app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue index 7a81950d5392c8..35ed20d1dd5702 100644 --- a/app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue +++ b/app/assets/javascripts/rapid_diffs/app/discussions/discussion_notes.vue @@ -1,13 +1,12 @@ + + diff --git a/app/assets/javascripts/rapid_diffs/app/discussions/note_header.vue b/app/assets/javascripts/rapid_diffs/app/discussions/note_header.vue index 0563bf483c1c51..828fda253442e4 100644 --- a/app/assets/javascripts/rapid_diffs/app/discussions/note_header.vue +++ b/app/assets/javascripts/rapid_diffs/app/discussions/note_header.vue @@ -4,6 +4,7 @@ import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils'; import { s__ } from '~/locale'; import ImportedBadge from '~/vue_shared/components/imported_badge.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import NoteAuthor from './note_author.vue'; export default { name: 'NoteHeader', @@ -14,6 +15,7 @@ export default { GlLoadingIcon, GlAvatarLink, GlAvatar, + NoteAuthor, }, directives: { GlTooltip: GlTooltipDirective, @@ -98,20 +100,7 @@ export default { - - - @{{ author.username }} - - - + {{ __('A deleted user') }} diff --git a/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue b/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue new file mode 100644 index 00000000000000..871d8d5f62da54 --- /dev/null +++ b/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js b/spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js index 6196ca0b6edf4b..09fdc64fcd85ef 100644 --- a/spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js +++ b/spec/frontend/rapid_diffs/app/discussions/discussion_notes_spec.js @@ -5,15 +5,6 @@ import NoteableNote from '~/rapid_diffs/app/discussions/noteable_note.vue'; import SystemNote from '~/vue_shared/components/notes/system_note.vue'; import ToggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue'; -jest.mock('~/vue_shared/components/notes/system_note.vue', () => { - return { - props: jest.requireActual('~/vue_shared/components/notes/system_note.vue').default.props, - render() { - return null; - }, - }; -}); - describe('DiscussionNotes', () => { let wrapper; @@ -28,9 +19,6 @@ describe('DiscussionNotes', () => { propsData, provide: merge(defaultProvisions, provide), scopedSlots, - stubs: { - SystemNote, - }, }); }; diff --git a/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js b/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js new file mode 100644 index 00000000000000..45350e12212a44 --- /dev/null +++ b/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js @@ -0,0 +1,72 @@ +import { shallowMount } from '@vue/test-utils'; +import NoteAuthor from '~/rapid_diffs/app/discussions/note_author.vue'; + +describe('NoteAuthor', () => { + let wrapper; + + const createComponent = (props = {}, slots = {}) => { + wrapper = shallowMount(NoteAuthor, { + propsData: props, + slots, + }); + }; + + const findAuthorLink = () => wrapper.find('a'); + + it('renders link with author path', () => { + const author = { + id: 'gid://gitlab/User/123', + name: 'John Doe', + username: 'johndoe', + path: '/johndoe', + }; + createComponent({ author }); + + const link = findAuthorLink(); + expect(link.exists()).toBe(true); + expect(link.attributes('href')).toBe('/johndoe'); + expect(link.text()).toBe('John Doe@johndoe'); + expect(link.attributes('data-user-id')).toBe('123'); + expect(link.attributes('data-username')).toBe('johndoe'); + }); + + it('skips username when not present', () => { + const author = { + id: 'gid://gitlab/User/123', + name: 'John Doe', + username: undefined, + path: '/johndoe', + }; + createComponent({ author }); + + const link = findAuthorLink(); + expect(link.text()).toBe('John Doe'); + }); + + it('uses webUrl when path is not available', () => { + const author = { + id: 'gid://gitlab/User/123', + name: 'John Doe', + username: 'johndoe', + webUrl: 'https://example.com/johndoe', + }; + createComponent({ author }); + + expect(findAuthorLink().attributes('href')).toBe('https://example.com/johndoe'); + }); + + it('renders note-header-info slot content', () => { + const author = { + id: 'gid://gitlab/User/123', + name: 'John Doe', + username: 'johndoe', + path: '/johndoe', + }; + createComponent( + { author }, + { 'note-header-info': 'Custom Info' }, + ); + + expect(wrapper.html()).toContain('Custom Info'); + }); +}); diff --git a/spec/frontend/rapid_diffs/app/discussions/note_header_spec.js b/spec/frontend/rapid_diffs/app/discussions/note_header_spec.js index 5338401bfa5003..8036c848172f1f 100644 --- a/spec/frontend/rapid_diffs/app/discussions/note_header_spec.js +++ b/spec/frontend/rapid_diffs/app/discussions/note_header_spec.js @@ -3,6 +3,7 @@ import { GlAvatar, GlAvatarLink, GlBadge, GlLoadingIcon } from '@gitlab/ui'; import NoteHeader from '~/rapid_diffs/app/discussions/note_header.vue'; import ImportedBadge from '~/vue_shared/components/imported_badge.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import NoteAuthor from '~/rapid_diffs/app/discussions/note_author.vue'; describe('NoteHeader', () => { let wrapper; @@ -42,7 +43,7 @@ describe('NoteHeader', () => { }); }); - it('shows author name and username', () => { + it('shows author', () => { const author = { id: 'gid://gitlab/User/123', name: 'John Doe', @@ -50,35 +51,7 @@ describe('NoteHeader', () => { path: '/johndoe', }; createComponent({ author }); - const authorLink = findAuthorLink(); - expect(authorLink.exists()).toBe(true); - expect(authorLink.attributes('href')).toBe('/johndoe'); - expect(authorLink.attributes('data-user-id')).toBe('123'); - expect(authorLink.attributes('data-username')).toBe('johndoe'); - expect(authorLink.text()).toContain('John Doe'); - expect(authorLink.text()).toContain('@johndoe'); - }); - - it('uses webUrl when path is not available', () => { - const author = { - id: 'gid://gitlab/User/123', - name: 'John Doe', - username: 'johndoe', - webUrl: 'https://example.com/johndoe', - }; - createComponent({ author }); - expect(findAuthorLink().attributes('href')).toBe('https://example.com/johndoe'); - }); - - it('shows username', () => { - const author = { - id: 'gid://gitlab/User/123', - name: 'John Doe', - username: 'johndoe', - path: '/johndoe', - }; - createComponent({ author }); - expect(wrapper.text()).toContain(author.username); + expect(wrapper.findComponent(NoteAuthor).props('author')).toStrictEqual(author); }); it('shows deleted user message instead of user link when no author is provided', () => { diff --git a/spec/frontend/rapid_diffs/app/discussions/system_note_spec.js b/spec/frontend/rapid_diffs/app/discussions/system_note_spec.js new file mode 100644 index 00000000000000..ad69b5960958ad --- /dev/null +++ b/spec/frontend/rapid_diffs/app/discussions/system_note_spec.js @@ -0,0 +1,31 @@ +import { shallowMount } from '@vue/test-utils'; +import SystemNote from '~/rapid_diffs/app/discussions/system_note.vue'; +import NoteAuthor from '~/rapid_diffs/app/discussions/note_author.vue'; + +describe('SystemNote', () => { + let wrapper; + + const createComponent = (props = {}) => { + wrapper = shallowMount(SystemNote, { + propsData: props, + }); + }; + + it('shows system message', () => { + const note = { note_html: '

test

' }; + createComponent({ note }); + expect(wrapper.find('p#test').text()).toBe('test'); + }); + + it('shows message author', () => { + const note = { note_html: 'test', author: { username: 'user' } }; + createComponent({ note }); + expect(wrapper.findComponent(NoteAuthor).props('author')).toStrictEqual(note.author); + }); + + it('shows deleted author', () => { + const note = { note_html: 'test' }; + createComponent({ note }); + expect(wrapper.text()).toContain('A deleted user'); + }); +}); -- GitLab From 5506201da4b91dfbf0745255215ef7a9508b23b1 Mon Sep 17 00:00:00 2001 From: Stanislav Lashmanov Date: Fri, 28 Nov 2025 15:04:40 +0400 Subject: [PATCH 2/4] Remove unnecessary slot --- .../rapid_diffs/app/discussions/note_author.vue | 7 +++---- .../app/discussions/note_author_spec.js | 15 --------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/rapid_diffs/app/discussions/note_author.vue b/app/assets/javascripts/rapid_diffs/app/discussions/note_author.vue index 72071267d922da..718f155a89e843 100644 --- a/app/assets/javascripts/rapid_diffs/app/discussions/note_author.vue +++ b/app/assets/javascripts/rapid_diffs/app/discussions/note_author.vue @@ -26,10 +26,9 @@ export default { > @{{ author.username }} - @{{ author.username }} - -
diff --git a/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js b/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js index 45350e12212a44..a3c56440e976aa 100644 --- a/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js +++ b/spec/frontend/rapid_diffs/app/discussions/note_author_spec.js @@ -54,19 +54,4 @@ describe('NoteAuthor', () => { expect(findAuthorLink().attributes('href')).toBe('https://example.com/johndoe'); }); - - it('renders note-header-info slot content', () => { - const author = { - id: 'gid://gitlab/User/123', - name: 'John Doe', - username: 'johndoe', - path: '/johndoe', - }; - createComponent( - { author }, - { 'note-header-info': 'Custom Info' }, - ); - - expect(wrapper.html()).toContain('Custom Info'); - }); }); -- GitLab From 52cfe21ac30791580b980efdd81a83dbf38ca0ab Mon Sep 17 00:00:00 2001 From: Stanislav Lashmanov Date: Fri, 28 Nov 2025 15:18:50 +0400 Subject: [PATCH 3/4] Add timestamp --- .../rapid_diffs/app/discussions/system_note.vue | 7 +++++-- .../rapid_diffs/app/discussions/system_note_spec.js | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue b/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue index 871d8d5f62da54..cc181349d911ff 100644 --- a/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue +++ b/app/assets/javascripts/rapid_diffs/app/discussions/system_note.vue @@ -1,11 +1,13 @@