diff --git a/ui/src/components/IssueChatThread.test.tsx b/ui/src/components/IssueChatThread.test.tsx index 0d8c4a35198..47dc0c0a683 100644 --- a/ui/src/components/IssueChatThread.test.tsx +++ b/ui/src/components/IssueChatThread.test.tsx @@ -1029,7 +1029,9 @@ describe("IssueChatThread", () => { }); expect(onAttachImage).toHaveBeenCalledWith(file); - expect(container.querySelector('[data-testid="issue-chat-composer-attachments"]')).not.toBeNull(); + const attachmentList = container.querySelector('[data-testid="issue-chat-composer-attachments"]'); + expect(attachmentList).not.toBeNull(); + expect(attachmentList?.className).toContain("mb-3"); expect(container.textContent).toContain("report.pdf"); expect(container.textContent).toContain("Attached to issue"); diff --git a/ui/src/components/IssueChatThread.tsx b/ui/src/components/IssueChatThread.tsx index ca1b6d83940..7eefffc7c17 100644 --- a/ui/src/components/IssueChatThread.tsx +++ b/ui/src/components/IssueChatThread.tsx @@ -2363,7 +2363,7 @@ const IssueChatComposer = forwardRef 0 ? (
{composerAttachments.map((attachment) => { const sizeLabel = formatAttachmentSize(attachment.size); diff --git a/ui/src/components/MarkdownEditor.test.tsx b/ui/src/components/MarkdownEditor.test.tsx index 4cc69444bfa..e4e52ae99b6 100644 --- a/ui/src/components/MarkdownEditor.test.tsx +++ b/ui/src/components/MarkdownEditor.test.tsx @@ -428,6 +428,31 @@ describe("MarkdownEditor", () => { }); }); + it("does not show the raw fallback while image-only markdown is settling", async () => { + mdxEditorMockState.emitMountSilentEmptyState = true; + const root = createRoot(container); + + await act(async () => { + root.render( + {}} + placeholder="Markdown body" + />, + ); + }); + + await flush(); + await flush(); + + expect(container.querySelector("textarea")).toBeNull(); + expect(container.textContent).not.toContain("Rich editor unavailable for this markdown"); + + await act(async () => { + root.unmount(); + }); + }); + it("anchors the mention menu inside the visual viewport when mobile offsets are present", () => { expect( computeMentionMenuPosition( diff --git a/ui/src/components/MarkdownEditor.tsx b/ui/src/components/MarkdownEditor.tsx index 4c604eee450..0ca8e0b6d87 100644 --- a/ui/src/components/MarkdownEditor.tsx +++ b/ui/src/components/MarkdownEditor.tsx @@ -128,6 +128,10 @@ function hasMeaningfulEditorContent(node: Node | null): boolean { return Array.from(element.childNodes).some((child) => hasMeaningfulEditorContent(child)); } +function hasMarkdownImage(value: string): boolean { + return /!\[[\s\S]*?\]\([^)]+\)/.test(value); +} + function isRichEditorDomEmpty( editable: HTMLElement, expectedValue: string, @@ -135,9 +139,11 @@ function isRichEditorDomEmpty( ): boolean { const expectedText = expectedValue.trim(); if (!expectedText) return false; + const expectedHasImage = hasMarkdownImage(expectedText); const visibleText = (editable.textContent ?? "").trim(); if (visibleText.length === 0) { + if (expectedHasImage) return false; return !Array.from(editable.childNodes).some((child) => hasMeaningfulEditorContent(child)); } @@ -147,6 +153,7 @@ function isRichEditorDomEmpty( && visibleText === normalizedPlaceholder && expectedText !== normalizedPlaceholder ) { + if (expectedHasImage) return false; return true; }