Skip to content

Commit 09d2075

Browse files
committed
Don't return inbox msgs with _cio prefixed topics by default
1 parent 678e989 commit 09d2075

File tree

2 files changed

+172
-1
lines changed

2 files changed

+172
-1
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { Analytics } from '../../../core/analytics'
2+
import { createInboxAPI, GistInboxMessage } from '../inbox_messages'
3+
4+
function makeMessage(
5+
overrides: Partial<GistInboxMessage> = {}
6+
): GistInboxMessage {
7+
return {
8+
messageType: 'inline',
9+
expiry: '',
10+
priority: 0,
11+
type: 'test',
12+
properties: {},
13+
queueId: `msg-${Math.random().toString(36).slice(2)}`,
14+
userToken: 'user-1',
15+
deliveryId: 'delivery-1',
16+
sentAt: new Date().toISOString(),
17+
opened: false,
18+
...overrides,
19+
}
20+
}
21+
22+
function createMockGist(messages: GistInboxMessage[]) {
23+
const listeners: Record<string, Function[]> = {}
24+
return {
25+
getInboxMessages: jest.fn().mockResolvedValue(messages),
26+
updateInboxMessageOpenState: jest.fn(),
27+
removeInboxMessage: jest.fn(),
28+
events: {
29+
on: jest.fn((event: string, cb: Function) => {
30+
if (!listeners[event]) listeners[event] = []
31+
listeners[event].push(cb)
32+
}),
33+
off: jest.fn(),
34+
emit: (event: string, data: any) => {
35+
;(listeners[event] || []).forEach((cb) => cb(data))
36+
},
37+
},
38+
}
39+
}
40+
41+
describe('Inbox _cio topic filtering', () => {
42+
const analytics = { track: jest.fn() } as unknown as Analytics
43+
44+
const regularMessage = makeMessage({
45+
queueId: 'regular',
46+
topics: ['news'],
47+
})
48+
const noTopicMessage = makeMessage({
49+
queueId: 'no-topic',
50+
topics: [],
51+
})
52+
const cioMessage = makeMessage({
53+
queueId: 'cio-msg',
54+
topics: ['_cio_inbox_5'],
55+
})
56+
const mixedMessage = makeMessage({
57+
queueId: 'mixed-msg',
58+
topics: ['news', '_cio_feed'],
59+
})
60+
61+
const allMessages = [regularMessage, noTopicMessage, cioMessage, mixedMessage]
62+
63+
describe('no topics specified', () => {
64+
it('should return messages without _cio topics', async () => {
65+
const gist = createMockGist(allMessages)
66+
const inbox = createInboxAPI(analytics, gist, [])
67+
68+
const messages = await inbox.messages()
69+
const ids = messages.map((m) => m.messageId)
70+
71+
expect(ids).toContain('regular')
72+
expect(ids).toContain('no-topic')
73+
expect(ids).not.toContain('cio-msg')
74+
expect(ids).not.toContain('mixed-msg')
75+
})
76+
77+
it('should not count _cio messages in total', async () => {
78+
const gist = createMockGist(allMessages)
79+
const inbox = createInboxAPI(analytics, gist, [])
80+
81+
expect(await inbox.total()).toBe(2)
82+
})
83+
84+
it('should not count _cio messages in totalUnopened', async () => {
85+
const gist = createMockGist(allMessages)
86+
const inbox = createInboxAPI(analytics, gist, [])
87+
88+
expect(await inbox.totalUnopened()).toBe(2)
89+
})
90+
91+
it('should filter _cio messages in onUpdates', async () => {
92+
const gist = createMockGist(allMessages)
93+
const inbox = createInboxAPI(analytics, gist, [])
94+
95+
const result = await new Promise<any[]>((resolve) => {
96+
inbox.onUpdates((messages) => resolve(messages))
97+
gist.events.emit('messageInboxUpdated', allMessages)
98+
})
99+
100+
const ids = result.map((m) => m.messageId)
101+
expect(ids).toContain('regular')
102+
expect(ids).toContain('no-topic')
103+
expect(ids).not.toContain('cio-msg')
104+
expect(ids).not.toContain('mixed-msg')
105+
})
106+
})
107+
108+
describe('non-_cio topic specified', () => {
109+
it('should return matching messages but exclude _cio messages', async () => {
110+
const gist = createMockGist(allMessages)
111+
const inbox = createInboxAPI(analytics, gist, ['news'])
112+
113+
const messages = await inbox.messages()
114+
const ids = messages.map((m) => m.messageId)
115+
116+
expect(ids).toContain('regular')
117+
expect(ids).not.toContain('no-topic')
118+
expect(ids).not.toContain('cio-msg')
119+
// mixed-msg has 'news' but also has '_cio_feed', should be excluded
120+
expect(ids).not.toContain('mixed-msg')
121+
})
122+
123+
it('should not count _cio messages in total', async () => {
124+
const gist = createMockGist(allMessages)
125+
const inbox = createInboxAPI(analytics, gist, ['news'])
126+
127+
expect(await inbox.total()).toBe(1)
128+
})
129+
})
130+
131+
describe('_cio topic explicitly specified', () => {
132+
it('should return _cio messages when explicitly requested', async () => {
133+
const gist = createMockGist(allMessages)
134+
const inbox = createInboxAPI(analytics, gist, ['_cio_inbox_5'])
135+
136+
const messages = await inbox.messages()
137+
const ids = messages.map((m) => m.messageId)
138+
139+
expect(ids).toContain('cio-msg')
140+
expect(ids).not.toContain('mixed-msg')
141+
expect(ids).not.toContain('regular')
142+
expect(ids).not.toContain('no-topic')
143+
})
144+
145+
it('should return _cio messages when a _cio topic is requested alongside others', async () => {
146+
const gist = createMockGist(allMessages)
147+
const inbox = createInboxAPI(analytics, gist, ['news', '_cio_feed'])
148+
149+
const messages = await inbox.messages()
150+
const ids = messages.map((m) => m.messageId)
151+
152+
expect(ids).toContain('regular')
153+
expect(ids).toContain('mixed-msg')
154+
expect(ids).not.toContain('no-topic')
155+
expect(ids).not.toContain('cio-msg')
156+
})
157+
})
158+
})

packages/browser/src/plugins/in-app-plugin/inbox_messages.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Analytics } from '../../core/analytics'
22
import { JourneysEvents } from './events'
33

4+
const CIO_TOPIC_PREFIX = '_cio'
5+
46
export interface GistInboxMessage {
57
messageType: string
68
expiry: string
@@ -143,14 +145,25 @@ async function getFilteredMessages(
143145
})
144146

145147
if (topics.length === 0) {
146-
return allMessages
148+
return allMessages.filter((message) => {
149+
const messageTopics = message.topics
150+
if (!messageTopics || messageTopics.length === 0) {
151+
return true
152+
}
153+
return !messageTopics.some((topic) => topic.startsWith(CIO_TOPIC_PREFIX))
154+
})
147155
}
148156

157+
const hasCioTopic = topics.some((topic) => topic.startsWith(CIO_TOPIC_PREFIX))
158+
149159
return allMessages.filter((message) => {
150160
const messageTopics = message.topics
151161
if (!messageTopics || messageTopics.length === 0) {
152162
return false
153163
}
164+
if (!hasCioTopic && messageTopics.some((topic) => topic.startsWith(CIO_TOPIC_PREFIX))) {
165+
return false
166+
}
154167
return messageTopics.some((messageTopic) => topics.includes(messageTopic))
155168
})
156169
}

0 commit comments

Comments
 (0)