Skip to content

Commit 3744358

Browse files
committed
Rudimentary integration test between the tabs and hub.
1 parent 6d7cd11 commit 3744358

File tree

2 files changed

+174
-28
lines changed

2 files changed

+174
-28
lines changed
Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,51 @@
11
import type { CommentDraft, CommentEvent, CommentSpot } from '../lib/enhancer'
22
import { JsonMap } from '../lib/jsonmap'
33

4-
interface Tab {
4+
export interface Tab {
55
tabId: number
66
windowId: number
77
}
8-
interface TabAndSpot {
8+
export interface TabAndSpot {
99
tab: Tab
1010
spot: CommentSpot
1111
}
12-
interface CommentState {
12+
export interface CommentState {
1313
tab: Tab
1414
spot: CommentSpot
1515
drafts: [number, CommentDraft][]
1616
}
1717

18-
const states = new JsonMap<TabAndSpot, CommentState>()
18+
export const states = new JsonMap<TabAndSpot, CommentState>()
1919

20-
export default defineBackground(() => {
21-
browser.runtime.onMessage.addListener((message: CommentEvent, sender) => {
22-
if (
23-
(message.type === 'ENHANCED' || message.type === 'DESTROYED') &&
24-
sender.tab?.id &&
25-
sender.tab?.windowId
26-
) {
27-
const tab: Tab = {
28-
tabId: sender.tab.id,
29-
windowId: sender.tab.windowId,
30-
}
20+
export function handleCommentEvent(message: CommentEvent, sender: any): void {
21+
if (
22+
(message.type === 'ENHANCED' || message.type === 'DESTROYED') &&
23+
sender.tab?.id &&
24+
sender.tab?.windowId
25+
) {
26+
const tab: Tab = {
27+
tabId: sender.tab.id,
28+
windowId: sender.tab.windowId,
29+
}
30+
31+
const tabAndSpot: TabAndSpot = {
32+
spot: message.spot,
33+
tab,
34+
}
3135

32-
const tabAndSpot: TabAndSpot = {
36+
if (message.type === 'ENHANCED') {
37+
const commentState: CommentState = {
38+
drafts: [],
3339
spot: message.spot,
3440
tab,
3541
}
36-
37-
if (message.type === 'ENHANCED') {
38-
const commentState: CommentState = {
39-
drafts: [],
40-
spot: message.spot,
41-
tab,
42-
}
43-
states.set(tabAndSpot, commentState)
44-
} else if (message.type === 'DESTROYED') {
45-
states.delete(tabAndSpot)
46-
}
42+
states.set(tabAndSpot, commentState)
43+
} else if (message.type === 'DESTROYED') {
44+
states.delete(tabAndSpot)
4745
}
48-
})
46+
}
47+
}
48+
49+
export default defineBackground(() => {
50+
browser.runtime.onMessage.addListener(handleCommentEvent)
4951
})
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { beforeEach, describe, expect, it } from 'vitest'
2+
import { handleCommentEvent, states } from '../src/entrypoints/background'
3+
import type { CommentEvent, CommentSpot } from '../src/lib/enhancer'
4+
5+
describe('Background Event Handler', () => {
6+
let mockSender: any
7+
let mockSpot: CommentSpot
8+
9+
beforeEach(() => {
10+
// Clear the shared states map before each test
11+
states.clear()
12+
13+
mockSender = {
14+
tab: {
15+
id: 123,
16+
windowId: 456,
17+
},
18+
}
19+
20+
mockSpot = {
21+
type: 'TEST_SPOT',
22+
unique_key: 'test-key',
23+
}
24+
})
25+
26+
describe('ENHANCED Event', () => {
27+
it('should create new comment state when textarea is enhanced', () => {
28+
const message: CommentEvent = {
29+
draft: undefined,
30+
spot: mockSpot,
31+
type: 'ENHANCED',
32+
}
33+
34+
handleCommentEvent(message, mockSender)
35+
36+
const expectedKey = {
37+
spot: mockSpot,
38+
tab: { tabId: 123, windowId: 456 },
39+
}
40+
41+
const state = states.get(expectedKey)
42+
expect(state).toBeDefined()
43+
expect(state?.tab).toEqual({ tabId: 123, windowId: 456 })
44+
expect(state?.spot).toEqual(mockSpot)
45+
expect(state?.drafts).toEqual([])
46+
})
47+
48+
it('should not handle ENHANCED event without tab info', () => {
49+
const message: CommentEvent = {
50+
draft: undefined,
51+
spot: mockSpot,
52+
type: 'ENHANCED',
53+
}
54+
55+
const senderWithoutTab = { tab: null }
56+
57+
handleCommentEvent(message, senderWithoutTab)
58+
59+
expect(states.size).toBe(0)
60+
})
61+
})
62+
63+
describe('DESTROYED Event', () => {
64+
it('should remove comment state when textarea is destroyed', () => {
65+
// First create a state using the actual handler
66+
const enhanceMessage: CommentEvent = {
67+
draft: undefined,
68+
spot: mockSpot,
69+
type: 'ENHANCED',
70+
}
71+
72+
handleCommentEvent(enhanceMessage, mockSender)
73+
expect(states.size).toBe(1)
74+
75+
// Then destroy it
76+
const destroyMessage: CommentEvent = {
77+
draft: undefined,
78+
spot: mockSpot,
79+
type: 'DESTROYED',
80+
}
81+
82+
handleCommentEvent(destroyMessage, mockSender)
83+
84+
expect(states.size).toBe(0)
85+
})
86+
87+
it('should handle DESTROYED event for non-existent state gracefully', () => {
88+
const message: CommentEvent = {
89+
draft: undefined,
90+
spot: mockSpot,
91+
type: 'DESTROYED',
92+
}
93+
94+
// Should not throw error
95+
handleCommentEvent(message, mockSender)
96+
97+
expect(states.size).toBe(0)
98+
})
99+
})
100+
101+
describe('Invalid Events', () => {
102+
it('should ignore events with unsupported type', () => {
103+
const message: CommentEvent = {
104+
draft: undefined,
105+
spot: mockSpot,
106+
type: 'LOST_FOCUS',
107+
}
108+
109+
handleCommentEvent(message, mockSender)
110+
111+
expect(states.size).toBe(0)
112+
})
113+
})
114+
115+
describe('State Management', () => {
116+
it('should handle multiple enhanced textareas from different tabs', () => {
117+
const spot1: CommentSpot = { type: 'SPOT1', unique_key: 'key1' }
118+
const spot2: CommentSpot = { type: 'SPOT2', unique_key: 'key2' }
119+
120+
const sender1 = { tab: { id: 123, windowId: 456 } }
121+
const sender2 = { tab: { id: 789, windowId: 456 } }
122+
123+
handleCommentEvent({ draft: undefined, spot: spot1, type: 'ENHANCED' }, sender1)
124+
handleCommentEvent({ draft: undefined, spot: spot2, type: 'ENHANCED' }, sender2)
125+
126+
expect(states.size).toBe(2)
127+
})
128+
129+
it('should handle same spot from same tab (overwrite)', () => {
130+
const message: CommentEvent = {
131+
draft: undefined,
132+
spot: mockSpot,
133+
type: 'ENHANCED',
134+
}
135+
136+
// Enhance same spot twice
137+
handleCommentEvent(message, mockSender)
138+
handleCommentEvent(message, mockSender)
139+
140+
// Should still be 1 entry (overwritten)
141+
expect(states.size).toBe(1)
142+
})
143+
})
144+
})

0 commit comments

Comments
 (0)