Conversation
📝 WalkthroughWalkthroughReplaces external-store positioning with local useState/useEffect and ResizeObserver in WaveMentionsTypeaheadMenu, adds an anchorElement prop, updates WaveMentionsPlugin to pass the anchor, and adds comprehensive tests for positioning, selection, and node creation/emission. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx (1)
14-24: Make viewport-dependent positioning tests deterministic.These assertions rely on ambient
window.innerHeight; pinning it in setup will reduce flakiness across test environments.💡 Suggested patch
describe("WaveMentionsTypeaheadMenu", () => { + const originalInnerHeight = window.innerHeight; const baseRect = { @@ beforeEach(() => { + Object.defineProperty(window, "innerHeight", { + configurable: true, + value: 800, + }); getBoundingClientRectMock = jest .spyOn(HTMLElement.prototype, "getBoundingClientRect") .mockReturnValue(baseRect as DOMRect); }); afterEach(() => { + Object.defineProperty(window, "innerHeight", { + configurable: true, + value: originalInnerHeight, + }); getBoundingClientRectMock.mockRestore(); jest.clearAllMocks(); });Also applies to: 54-59
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx` around lines 14 - 24, Tests use viewport-dependent values via baseRect and rely on window.innerHeight, causing flakiness; make them deterministic by pinning window.innerHeight to a fixed value in the test setup and restoring it afterwards. Add a beforeEach or beforeAll that sets window.innerHeight = <fixedNumber> (e.g., 800) before tests that use baseRect (and the related assertions around lines 54-59), and an afterEach/afterAll that restores the original innerHeight to avoid side effects. Ensure the change targets the test file WaveMentionsTypeaheadMenu.test.tsx and affects both occurrences of baseRect-based assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.tsx`:
- Around line 26-34: The current position calculation uses the
already-positioned menu's bounding rect (variable element/getBoundingClientRect)
which biases measurements by the menu height; change it to measure the anchor's
geometry instead: obtain the anchor's bounding rect (e.g.,
anchorElement.getBoundingClientRect() or the selection/anchor node rect) and
compute spaceAbove = anchorRect.top and spaceBelow = window.innerHeight -
anchorRect.bottom, then pick nextPosition ("top"|"bottom") from those values and
call setPosition as before (keep the setPosition(current => current ===
nextPosition ? current : nextPosition) logic). Ensure you reference the anchor
element/rect rather than the menu element/rect when computing
spaceAbove/spaceBelow.
---
Nitpick comments:
In
`@__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx`:
- Around line 14-24: Tests use viewport-dependent values via baseRect and rely
on window.innerHeight, causing flakiness; make them deterministic by pinning
window.innerHeight to a fixed value in the test setup and restoring it
afterwards. Add a beforeEach or beforeAll that sets window.innerHeight =
<fixedNumber> (e.g., 800) before tests that use baseRect (and the related
assertions around lines 54-59), and an afterEach/afterAll that restores the
original innerHeight to avoid side effects. Ensure the change targets the test
file WaveMentionsTypeaheadMenu.test.tsx and affects both occurrences of
baseRect-based assertions.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsPlugin.test.tsx__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsxcomponents/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.tsx
Signed-off-by: Simo <simo@6529.io>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.tsx`:
- Around line 60-75: The menu position only updates on window resize and menu
element resize, so scrolling or anchor movement leaves it stale; modify the
effect that sets up updatePosition (including the win.addEventListener("resize",
updatePosition) block and ResizeObserver usage) to also listen for scroll events
(e.g., window.addEventListener("scroll", updatePosition) with passive option)
and to observe the anchorElement with ResizeObserver in addition to
menuRef.current so changes to the anchor's size/position trigger updatePosition;
also ensure cleanup removes the scroll listener and disconnects the
ResizeObserver and still calls cancelInitialUpdate and
win.removeEventListener("resize", updatePosition) to fully tear down
(references: updatePosition, menuRef.current, anchorElement, ResizeObserver,
cancelInitialUpdate).
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
components/drops/create/lexical/plugins/waves/WaveMentionsPlugin.tsxcomponents/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.tsx
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx (1)
168-188: Tighten cleanup assertions to verify the exact listener references.
expect.any(Function)can still pass if cleanup removes a different callback. Capture the listener passed toaddEventListenerand assert the same reference is removed.Suggested test hardening
+ const resizeAddCall = addListenerSpy.mock.calls.find( + ([type]) => type === "resize" + ); + const scrollAddCall = addListenerSpy.mock.calls.find( + ([type]) => type === "scroll" + ); + const resizeHandler = resizeAddCall?.[1] as EventListener; + const scrollHandler = scrollAddCall?.[1] as EventListener; + expect(addListenerSpy).toHaveBeenCalledWith( "resize", expect.any(Function) ); expect(addListenerSpy).toHaveBeenCalledWith( "scroll", expect.any(Function), { passive: true } ); expect(observe).toHaveBeenCalledWith(anchorElement); unmount(); - expect(removeListenerSpy).toHaveBeenCalledWith( - "resize", - expect.any(Function) - ); - expect(removeListenerSpy).toHaveBeenCalledWith( - "scroll", - expect.any(Function) - ); + expect(removeListenerSpy).toHaveBeenCalledWith("resize", resizeHandler); + expect(removeListenerSpy).toHaveBeenCalledWith("scroll", scrollHandler); expect(disconnect).toHaveBeenCalledTimes(1);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx` around lines 168 - 188, The cleanup assertions use expect.any(Function) which can mask mismatched callbacks; change the test to capture the actual listener functions passed to addListenerSpy (inspect addListenerSpy.mock.calls to find the "resize" and "scroll" callback references after mounting) and then assert that removeListenerSpy was called with those same function references (use the captured resize and scroll callback variables) instead of expect.any(Function); keep the observe/assert and unmount sequence the same so you verify observe(anchorElement) and then unmount triggers removeListenerSpy calledWith the exact previously captured functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsx`:
- Around line 168-188: The cleanup assertions use expect.any(Function) which can
mask mismatched callbacks; change the test to capture the actual listener
functions passed to addListenerSpy (inspect addListenerSpy.mock.calls to find
the "resize" and "scroll" callback references after mounting) and then assert
that removeListenerSpy was called with those same function references (use the
captured resize and scroll callback variables) instead of expect.any(Function);
keep the observe/assert and unmount sequence the same so you verify
observe(anchorElement) and then unmount triggers removeListenerSpy calledWith
the exact previously captured functions.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
__tests__/components/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.test.tsxcomponents/drops/create/lexical/plugins/waves/WaveMentionsTypeaheadMenu.tsx

Summary by CodeRabbit
Tests
Refactor
Chore