From 523c56e56e12d4eb1077df47f6645298a5864d08 Mon Sep 17 00:00:00 2001 From: Asli Aykan Date: Wed, 20 Nov 2024 14:27:26 +0100 Subject: [PATCH 1/4] updated open dropdown function to disable it when there is link --- .../answer-post/answer-post.component.ts | 33 +++++++++------- .../app/shared/metis/post/post.component.ts | 33 +++++++++------- .../answer-post/answer-post.component.spec.ts | 38 +++++++++++++++++++ .../shared/metis/post/post.component.spec.ts | 38 +++++++++++++++++++ 4 files changed, 114 insertions(+), 28 deletions(-) diff --git a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts index 3b3c5e7ffdf1..e7d539291bc1 100644 --- a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts +++ b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts @@ -100,24 +100,29 @@ export class AnswerPostComponent extends PostingDirective { } onRightClick(event: MouseEvent) { - event.preventDefault(); + const targetElement = event.target as HTMLElement; + const isPointerCursor = window.getComputedStyle(targetElement).cursor === 'pointer'; - if (AnswerPostComponent.activeDropdownPost && AnswerPostComponent.activeDropdownPost !== this) { - AnswerPostComponent.activeDropdownPost.showDropdown = false; - AnswerPostComponent.activeDropdownPost.enableBodyScroll(); - AnswerPostComponent.activeDropdownPost.changeDetector.detectChanges(); - } + if (!isPointerCursor) { + event.preventDefault(); + + if (AnswerPostComponent.activeDropdownPost && AnswerPostComponent.activeDropdownPost !== this) { + AnswerPostComponent.activeDropdownPost.showDropdown = false; + AnswerPostComponent.activeDropdownPost.enableBodyScroll(); + AnswerPostComponent.activeDropdownPost.changeDetector.detectChanges(); + } - AnswerPostComponent.activeDropdownPost = this; + AnswerPostComponent.activeDropdownPost = this; - this.dropdownPosition = { - x: event.clientX, - y: event.clientY, - }; + this.dropdownPosition = { + x: event.clientX, + y: event.clientY, + }; - this.showDropdown = true; - this.adjustDropdownPosition(); - this.disableBodyScroll(); + this.showDropdown = true; + this.adjustDropdownPosition(); + this.disableBodyScroll(); + } } adjustDropdownPosition() { diff --git a/src/main/webapp/app/shared/metis/post/post.component.ts b/src/main/webapp/app/shared/metis/post/post.component.ts index d70c13abae68..c7a40a6641cd 100644 --- a/src/main/webapp/app/shared/metis/post/post.component.ts +++ b/src/main/webapp/app/shared/metis/post/post.component.ts @@ -121,24 +121,29 @@ export class PostComponent extends PostingDirective implements OnInit, OnC } onRightClick(event: MouseEvent) { - event.preventDefault(); + const targetElement = event.target as HTMLElement; + const isPointerCursor = window.getComputedStyle(targetElement).cursor === 'pointer'; - if (PostComponent.activeDropdownPost && PostComponent.activeDropdownPost !== this) { - PostComponent.activeDropdownPost.showDropdown = false; - PostComponent.activeDropdownPost.enableBodyScroll(); - PostComponent.activeDropdownPost.changeDetector.detectChanges(); - } + if (!isPointerCursor) { + event.preventDefault(); + + if (PostComponent.activeDropdownPost && PostComponent.activeDropdownPost !== this) { + PostComponent.activeDropdownPost.showDropdown = false; + PostComponent.activeDropdownPost.enableBodyScroll(); + PostComponent.activeDropdownPost.changeDetector.detectChanges(); + } - PostComponent.activeDropdownPost = this; + PostComponent.activeDropdownPost = this; - this.dropdownPosition = { - x: event.clientX, - y: event.clientY, - }; + this.dropdownPosition = { + x: event.clientX, + y: event.clientY, + }; - this.showDropdown = true; - this.adjustDropdownPosition(); - this.disableBodyScroll(); + this.showDropdown = true; + this.adjustDropdownPosition(); + this.disableBodyScroll(); + } } adjustDropdownPosition() { diff --git a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts index 247786e4fc12..2d8c8caa6930 100644 --- a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts +++ b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts @@ -175,4 +175,42 @@ describe('AnswerPostComponent', () => { expect(component.posting.reactions).toEqual(updatedReactions); }); + + it('should handle onRightClick correctly based on cursor style', () => { + const testCases = [ + { + cursor: 'pointer', + preventDefaultCalled: false, + showDropdown: false, + dropdownPosition: { x: 0, y: 0 }, + }, + { + cursor: 'default', + preventDefaultCalled: true, + showDropdown: true, + dropdownPosition: { x: 100, y: 200 }, + }, + ]; + + testCases.forEach(({ cursor, preventDefaultCalled, showDropdown, dropdownPosition }) => { + const event = new MouseEvent('contextmenu', { clientX: 100, clientY: 200 }); + + const targetElement = document.createElement('div'); + Object.defineProperty(event, 'target', { value: targetElement }); + + jest.spyOn(window, 'getComputedStyle').mockReturnValue({ + cursor, + } as CSSStyleDeclaration); + + const preventDefaultSpy = jest.spyOn(event, 'preventDefault'); + + component.onRightClick(event); + + expect(preventDefaultSpy).toHaveBeenCalledTimes(preventDefaultCalled ? 1 : 0); + expect(component.showDropdown).toBe(showDropdown); + expect(component.dropdownPosition).toEqual(dropdownPosition); + + jest.restoreAllMocks(); + }); + }); }); diff --git a/src/test/javascript/spec/component/shared/metis/post/post.component.spec.ts b/src/test/javascript/spec/component/shared/metis/post/post.component.spec.ts index cdcc598b7988..624bcb06f67b 100644 --- a/src/test/javascript/spec/component/shared/metis/post/post.component.spec.ts +++ b/src/test/javascript/spec/component/shared/metis/post/post.component.spec.ts @@ -311,4 +311,42 @@ describe('PostComponent', () => { expect(component.showDropdown).toBeFalse(); expect(enableBodyScrollSpy).toHaveBeenCalled(); }); + + it('should handle onRightClick correctly based on cursor style', () => { + const testCases = [ + { + cursor: 'pointer', + preventDefaultCalled: false, + showDropdown: false, + dropdownPosition: { x: 0, y: 0 }, + }, + { + cursor: 'default', + preventDefaultCalled: true, + showDropdown: true, + dropdownPosition: { x: 100, y: 200 }, + }, + ]; + + testCases.forEach(({ cursor, preventDefaultCalled, showDropdown, dropdownPosition }) => { + const event = new MouseEvent('contextmenu', { clientX: 100, clientY: 200 }); + + const targetElement = document.createElement('div'); + Object.defineProperty(event, 'target', { value: targetElement }); + + jest.spyOn(window, 'getComputedStyle').mockReturnValue({ + cursor, + } as CSSStyleDeclaration); + + const preventDefaultSpy = jest.spyOn(event, 'preventDefault'); + + component.onRightClick(event); + + expect(preventDefaultSpy).toHaveBeenCalledTimes(preventDefaultCalled ? 1 : 0); + expect(component.showDropdown).toBe(showDropdown); + expect(component.dropdownPosition).toEqual(dropdownPosition); + + jest.restoreAllMocks(); + }); + }); }); From d5c1d0f64ebdc0744802874cb75a44574d09bfdb Mon Sep 17 00:00:00 2001 From: Asli Aykan <56061820+asliayk@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:36:23 +0100 Subject: [PATCH 2/4] Update src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../metis/answer-post/answer-post.component.spec.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts index 2d8c8caa6930..a3d3692660bf 100644 --- a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts +++ b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts @@ -210,7 +210,12 @@ describe('AnswerPostComponent', () => { expect(component.showDropdown).toBe(showDropdown); expect(component.dropdownPosition).toEqual(dropdownPosition); - jest.restoreAllMocks(); - }); +afterEach(() => { + jest.restoreAllMocks(); +}); + +testCases.forEach(({ cursor, preventDefaultCalled, showDropdown, dropdownPosition }) => { + // ... test implementation ... +}); }); }); From 2a8e4bb5e5fa68d632d9d5e4de3030e8bfc170df Mon Sep 17 00:00:00 2001 From: Asli Aykan Date: Mon, 25 Nov 2024 10:48:53 +0100 Subject: [PATCH 3/4] refactor --- .../answer-post/answer-post.component.ts | 31 +++++++++++++++---- .../answer-post/answer-post.component.spec.ts | 13 +++----- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts index e7d539291bc1..0b8e696e1ba4 100644 --- a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts +++ b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts @@ -6,6 +6,7 @@ import { HostListener, Inject, Input, + OnDestroy, Output, Renderer2, ViewChild, @@ -34,7 +35,7 @@ import { AnswerPostReactionsBarComponent } from 'app/shared/metis/posting-reacti ]), ], }) -export class AnswerPostComponent extends PostingDirective { +export class AnswerPostComponent extends PostingDirective implements OnDestroy { @Input() lastReadDate?: dayjs.Dayjs; @Input() isLastAnswer: boolean; @Output() openPostingCreateEditModal = new EventEmitter(); @@ -101,15 +102,18 @@ export class AnswerPostComponent extends PostingDirective { onRightClick(event: MouseEvent) { const targetElement = event.target as HTMLElement; - const isPointerCursor = window.getComputedStyle(targetElement).cursor === 'pointer'; + let isPointerCursor = false; + try { + isPointerCursor = window.getComputedStyle(targetElement).cursor === 'pointer'; + } catch (error) { + console.error('Failed to compute style:', error); + } if (!isPointerCursor) { event.preventDefault(); - if (AnswerPostComponent.activeDropdownPost && AnswerPostComponent.activeDropdownPost !== this) { - AnswerPostComponent.activeDropdownPost.showDropdown = false; - AnswerPostComponent.activeDropdownPost.enableBodyScroll(); - AnswerPostComponent.activeDropdownPost.changeDetector.detectChanges(); + if (AnswerPostComponent.activeDropdownPost !== this) { + AnswerPostComponent.cleanupActiveDropdown(); } AnswerPostComponent.activeDropdownPost = this; @@ -133,4 +137,19 @@ export class AnswerPostComponent extends PostingDirective { this.dropdownPosition.x = screenWidth - dropdownWidth - 10; } } + + private static cleanupActiveDropdown(): void { + if (AnswerPostComponent.activeDropdownPost) { + AnswerPostComponent.activeDropdownPost.showDropdown = false; + AnswerPostComponent.activeDropdownPost.enableBodyScroll(); + AnswerPostComponent.activeDropdownPost.changeDetector.detectChanges(); + AnswerPostComponent.activeDropdownPost = null; + } + } + + ngOnDestroy(): void { + if (AnswerPostComponent.activeDropdownPost === this) { + AnswerPostComponent.cleanupActiveDropdown(); + } + } } diff --git a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts index a3d3692660bf..89600e6f7f8e 100644 --- a/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts +++ b/src/test/javascript/spec/component/shared/metis/answer-post/answer-post.component.spec.ts @@ -50,6 +50,10 @@ describe('AnswerPostComponent', () => { }); }); + afterEach(() => { + jest.restoreAllMocks(); + }); + it('should contain an answer post header when isConsecutive is false', () => { runInInjectionContext(fixture.debugElement.injector, () => { component.isConsecutive = input(false); @@ -209,13 +213,6 @@ describe('AnswerPostComponent', () => { expect(preventDefaultSpy).toHaveBeenCalledTimes(preventDefaultCalled ? 1 : 0); expect(component.showDropdown).toBe(showDropdown); expect(component.dropdownPosition).toEqual(dropdownPosition); - -afterEach(() => { - jest.restoreAllMocks(); -}); - -testCases.forEach(({ cursor, preventDefaultCalled, showDropdown, dropdownPosition }) => { - // ... test implementation ... -}); + }); }); }); From 6b5f1536fb8691135ed44c2b91c927a618c934fd Mon Sep 17 00:00:00 2001 From: Asli Aykan Date: Mon, 25 Nov 2024 11:05:05 +0100 Subject: [PATCH 4/4] refactor --- .../webapp/app/shared/metis/answer-post/answer-post.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts index 0b8e696e1ba4..12244ec7af39 100644 --- a/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts +++ b/src/main/webapp/app/shared/metis/answer-post/answer-post.component.ts @@ -107,6 +107,7 @@ export class AnswerPostComponent extends PostingDirective implements isPointerCursor = window.getComputedStyle(targetElement).cursor === 'pointer'; } catch (error) { console.error('Failed to compute style:', error); + isPointerCursor = true; } if (!isPointerCursor) {