1package webkit
2
3import (
4 "testing"
5
6 "github.com/bnema/puregotk/v4/webkit"
7 "github.com/stretchr/testify/assert"
8)
9
10// TestAccentDetectionScriptInjectionMode verifies that the accent detection
11// script is configured for all-frames injection (not top-frame only).
12// This ensures the script runs in iframes as well as the top-level document.
13func TestAccentDetectionScriptInjectionMode(t *testing.T) {
14 assert.Equal(t,
15 webkit.UserContentInjectAllFramesValue,
16 accentDetectionInjectionMode,
17 "accent detection script must inject into all frames, not just the top frame",
18 )
19}
20
21func TestAccentDetectionScriptTracksLastFocusedEditableElement(t *testing.T) {
22 script := buildAccentDetectionScript("")
23 assert.Contains(t,
24 script,
25 "window.__dumber_lastEditableEl = e.target",
26 "accent detection script must track the last focused editable element",
27 )
28 assert.Contains(t,
29 script,
30 "document.addEventListener('focusin'",
31 "accent detection script must register a focusin listener",
32 )
33 assert.Contains(t, script, "el.isContentEditable")
34 assert.Contains(t, script, "closest('[contenteditable]')")
35}
36
37func TestAccentDetectionScriptPostsEditableFocusChangedMessages(t *testing.T) {
38 script := buildAccentDetectionScript("")
39 assert.Contains(t, script, "editable_focus_changed")
40 assert.Contains(t, script, "document.addEventListener('focusout'")
41 assert.Contains(t, script, `const editableFocusToken = "";`)
42 assert.Contains(t, script, `payload: { editable: editable, token: editableFocusToken }`)
43 assert.Contains(t, script, "let lastEditableFocusState = null;")
44 assert.Contains(t, script, "if (lastEditableFocusState === editable) return;")
45 assert.Contains(t, script, `postEditableFocus(true)`)
46 assert.Contains(t, script, `postEditableFocus(false)`)
47 assert.Contains(t, script, `e && e.isTrusted === false`)
48 assert.Contains(t, script, `document.activeElement`)
49 assert.Contains(t, script, `window.__dumber_lastEditableEl = document.activeElement`)
50}
51
52func TestBuildAccentDetectionScript_EmptyTokenReturnsBeforeHandlerLookup(t *testing.T) {
53 empty := buildAccentDetectionScript("")
54 assert.Contains(t, empty, "if (!editableFocusToken) return;")
55 nonEmpty := buildAccentDetectionScript("abc123")
56 assert.Contains(t, nonEmpty, `const editableFocusToken = "abc123";`)
57 assert.Contains(t, nonEmpty, "if (!editableFocusToken) return;")
58 assert.Contains(t, nonEmpty, `postEditableFocus(true)`)
59 assert.Contains(t, nonEmpty, "window.webkit.messageHandlers.dumber.postMessage")
60}
61
62func TestExplicitCopyScriptCapturesClipboardOperations(t *testing.T) {
63 script := buildExplicitCopyScript()
64
65 assert.Contains(t, script, "explicit_text_copy")
66 assert.Contains(t, script, "document.addEventListener('copy'")
67 assert.Contains(t, script, "document.addEventListener('cut'")
68 assert.Contains(t, script, "document.execCommand")
69 assert.Contains(t, script, "navigator.clipboard.writeText")
70 assert.Contains(t, script, "navigator.userActivation")
71 assert.Contains(t, script, "var userActivated = hasUserActivation()")
72 assert.Contains(t, script, "if (userActivated)")
73 assert.Contains(t, script, "try {")
74 assert.Contains(t, script, "finally {")
75 assert.Contains(t, script, "pendingCommand === command")
76}
77
78func TestExplicitCopyScriptReadsInputAndTextareaSelectionFirst(t *testing.T) {
79 script := buildExplicitCopyScript()
80
81 assert.Contains(t, script, "document.activeElement")
82 assert.Contains(t, script, "selectionStart")
83 assert.Contains(t, script, "selectionEnd")
84 assert.Contains(t, script, "INPUT")
85 assert.Contains(t, script, "TEXTAREA")
86 assert.Contains(t, script, "type || '').toLowerCase()")
87 assert.Contains(t, script, "case 'password':")
88}