fix(web-chat): normalize chat copy to plain text (#1114)

* fix(web-chat): force plain-text clipboard copy from chat messages

* test(e2e): make chat copy test target deterministic message
This commit is contained in:
Nige
2026-03-15 05:52:47 +00:00
committed by GitHub
parent 3f6d2ab6c2
commit dac420840d
2 changed files with 57 additions and 0 deletions
+41
View File
@@ -74,3 +74,44 @@ async def test_empty_message_not_sent(page):
await page.wait_for_timeout(2000)
final_count = await page.locator(f"{SEL['message_user']}, {SEL['message_assistant']}").count()
assert final_count == initial_count, "Empty message should not create new messages"
async def test_copy_from_chat_forces_plain_text(page):
"""Copying selected chat text should populate plain text clipboard data only."""
await page.evaluate("addMessage('assistant', 'Copy me into Sheets')")
copied = await page.evaluate(
"""
() => {
const content = Array.from(document.querySelectorAll('#chat-messages .message.assistant .message-content'))
.find((el) => (el.textContent || '').includes('Copy me into Sheets'));
if (!content) return {ok: false, reason: 'no content'};
const range = document.createRange();
range.selectNodeContents(content);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
const store = {};
const evt = new Event('copy', { bubbles: true, cancelable: true });
evt.clipboardData = {
clearData: () => { Object.keys(store).forEach((k) => delete store[k]); },
setData: (t, v) => { store[t] = v; },
getData: (t) => store[t] || '',
};
content.dispatchEvent(evt);
return {
ok: true,
defaultPrevented: evt.defaultPrevented,
text: store['text/plain'] || '',
html: store['text/html'] || '',
};
}
"""
)
assert copied["ok"], copied.get("reason", "copy setup failed")
assert copied["defaultPrevented"] is True
assert "Copy me into Sheets" in copied["text"]
assert copied["html"] == ""