Skip to content

Commit c6ee227

Browse files
feat(chatwoot,#79): bridge opened/closed/startConversation/postback events
Chatwoot's SDK fires four CustomEvents we weren't forwarding to consumers: chatwoot:opened, chatwoot:closed, chatwoot:on-start-conversation, and chatwoot:postback. Plumb them through the existing bindDomEvent/on() typed emitter alongside the message/unreadCountChange/error events. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 87fbc3b commit c6ee227

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

src/providers/chatwoot.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,15 @@ const queue = createQueue<ChatwootAPI>()
4646
const store = createIdentityStore()
4747
const lifecycle = createLifecycle()
4848
const unreadListeners = new Set<(count: number) => void>()
49-
type ChatwootEventName = "ready" | "message" | "unreadCountChange" | "error"
49+
type ChatwootEventName =
50+
| "ready"
51+
| "message"
52+
| "unreadCountChange"
53+
| "error"
54+
| "opened"
55+
| "closed"
56+
| "startConversation"
57+
| "postback"
5058
const eventListeners = new Map<ChatwootEventName, Set<(payload: unknown) => void>>()
5159
let currentToken: string | undefined
5260
let currentBaseUrl: string | undefined
@@ -121,6 +129,10 @@ export async function load(options: ChatwootLoadOptions): Promise<void> {
121129
bindDomEvent("chatwoot:on-message", "message")
122130
bindDomEvent("chatwoot:on-unread-message-count-changed", "unreadCountChange")
123131
bindDomEvent("chatwoot:error", "error")
132+
bindDomEvent("chatwoot:opened", "opened")
133+
bindDomEvent("chatwoot:closed", "closed")
134+
bindDomEvent("chatwoot:on-start-conversation", "startConversation")
135+
bindDomEvent("chatwoot:postback", "postback")
124136

125137
try {
126138
await injectScript({

test/chatwoot.browser.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,37 @@ describe("chatwoot (browser) — vendor-doc audit fixes (#79)", () => {
115115
expect(rec.popoutChatWindow).toBe(1)
116116
await chatwoot.destroy()
117117
})
118+
119+
it("bridges chatwoot:opened / closed / on-start-conversation / postback", async () => {
120+
const rec: Recorded = {
121+
setColorScheme: [],
122+
deleteCustomAttribute: [],
123+
deleteConversationCustomAttribute: [],
124+
popoutChatWindow: 0,
125+
}
126+
const chatwoot = await bootChatwoot(rec)
127+
128+
const opened: unknown[] = []
129+
const closed: unknown[] = []
130+
const started: unknown[] = []
131+
const postbacks: unknown[] = []
132+
chatwoot.on("opened", (p) => opened.push(p))
133+
chatwoot.on("closed", (p) => closed.push(p))
134+
chatwoot.on("startConversation", (p) => started.push(p))
135+
chatwoot.on("postback", (p) => postbacks.push(p))
136+
137+
window.dispatchEvent(new CustomEvent("chatwoot:opened"))
138+
window.dispatchEvent(new CustomEvent("chatwoot:closed"))
139+
window.dispatchEvent(
140+
new CustomEvent("chatwoot:on-start-conversation", { detail: { source: "bubble" } }),
141+
)
142+
window.dispatchEvent(new CustomEvent("chatwoot:postback", { detail: { value: "yes" } }))
143+
144+
expect(opened).toHaveLength(1)
145+
expect(closed).toHaveLength(1)
146+
expect(started).toEqual([{ source: "bubble" }])
147+
expect(postbacks).toEqual([{ value: "yes" }])
148+
149+
await chatwoot.destroy()
150+
})
118151
})

0 commit comments

Comments
 (0)