Files
2026-07-13 13:34:48 +08:00

162 lines
5.0 KiB
TypeScript

import { expect, test } from 'vitest'
import _ from 'lodash'
import * as utils from './utils'
import * as config from './config'
import * as chat from '../src'
const apiUrl = config.get('API_URL')
const protocols = ['sse', 'websocket'] as const
test.each(protocols)('api allows adding and removing conversation participants', async (protocol) => {
const client = new chat.Client({ apiUrl })
const { key: userKey1 } = await client.createUser({})
const { user: user2, key: userKey2 } = await client.createUser({})
const { conversation } = await client.createConversation({ 'x-user-key': userKey1 })
const listener = await client.listenConversation({ id: conversation.id, 'x-user-key': userKey1, protocol })
await expect(
client.createMessage({
'x-user-key': userKey2,
conversationId: conversation.id,
payload: {
type: 'text',
text: 'hello world',
},
})
).rejects.toThrow(chat.ForbiddenError)
await Promise.all([
utils.waitFor(listener, 'participant_added'),
client.addParticipant({
'x-user-key': userKey1,
conversationId: conversation.id,
userId: user2.id,
}),
])
await expect(
client.createMessage({
'x-user-key': userKey2,
conversationId: conversation.id,
payload: {
type: 'text',
text: 'hello world',
},
})
).resolves.toBeTruthy()
await Promise.all([
utils.waitFor(listener, 'participant_removed'),
client.removeParticipant({
'x-user-key': userKey1,
conversationId: conversation.id,
userId: user2.id,
}),
])
await expect(
client.createMessage({
'x-user-key': userKey2,
conversationId: conversation.id,
payload: {
type: 'text',
text: 'hello world',
},
})
).rejects.toThrow(chat.ForbiddenError)
})
test('api forbids non-participants from listing participants', async () => {
const client = new chat.Client({ apiUrl })
const user1 = await client.createUser({})
const user2 = await client.createUser({})
const user3 = await client.createUser({})
const { conversation } = await client.createConversation({ 'x-user-key': user1.key })
await client.addParticipant({ 'x-user-key': user1.key, conversationId: conversation.id, userId: user2.user.id })
const promise1 = client.listParticipants({ 'x-user-key': user1.key, conversationId: conversation.id })
await expect(promise1).resolves.toBeTruthy()
const promise2 = client.listParticipants({ 'x-user-key': user2.key, conversationId: conversation.id })
await expect(promise2).resolves.toBeTruthy()
const promise3 = client.listParticipants({ 'x-user-key': user3.key, conversationId: conversation.id })
await expect(promise3).rejects.toThrow(chat.ForbiddenError)
})
test.each(protocols)('signal listener is disconnected when participant is removed', async (protocol) => {
const client = new chat.Client({ apiUrl })
const { user: user1, key: userKey1 } = await client.createUser({})
const { user: user2, key: userKey2 } = await client.createUser({})
const { conversation } = await client.createConversation({ 'x-user-key': userKey1 })
await client.addParticipant({ 'x-user-key': userKey1, conversationId: conversation.id, userId: user2.id })
const listener1 = await client.listenConversation({ id: conversation.id, 'x-user-key': userKey1, protocol })
const listener2 = await client.listenConversation({ id: conversation.id, 'x-user-key': userKey2, protocol })
const messages1: chat.Signals['message_created'][] = []
const messages2: chat.Signals['message_created'][] = []
listener1.on('message_created', (message) => messages1.push(message))
listener2.on('message_created', (message) => messages2.push(message))
await Promise.all([
utils.waitFor(listener1, 'message_created'),
client.createMessage({
'x-user-key': userKey1,
conversationId: conversation.id,
payload: {
type: 'text',
text: 'foo',
},
}),
])
await client.removeParticipant({ 'x-user-key': userKey1, conversationId: conversation.id, userId: user2.id })
await Promise.all([
utils.waitFor(listener1, 'message_created'),
client.createMessage({
'x-user-key': userKey1,
conversationId: conversation.id,
payload: {
type: 'text',
text: 'bar',
},
}),
])
const incomingMessages1 = messages1.filter((m) => !m.isBot)
const incomingMessages2 = messages2.filter((m) => !m.isBot)
expect(incomingMessages1.length).toBe(2)
expect(incomingMessages2.length).toBe(1)
await listener1.disconnect()
listener1.cleanup()
await listener2.disconnect()
listener2.cleanup()
})
test('api forbids removing owner from conversation participants', async () => {
const client = new chat.Client({ apiUrl })
const { user: user1, key: userKey1 } = await client.createUser({})
const { conversation } = await client.createConversation({ 'x-user-key': userKey1 })
await expect(
client.removeParticipant({
'x-user-key': userKey1,
conversationId: conversation.id,
userId: user1.id,
})
).rejects.toThrow(chat.InvalidPayloadError)
})