mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-01 06:29:16 +00:00
bots: SimpleX Calculator demo bot (#7583)
* bots: SimpleX Calculator demo bot * refactor * use local server in test * simplify * icon * simplify * expression * replies * improve * log * update name in bot address * @simplex-chat/type: 0.12.0 * simplex-chat nodejs: 7.1.0-beta.4.2 * update dependencies * option to add domain to bot address --------- Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
co-authored by
Evgeny @ SimpleX Chat
parent
4cb244441b
commit
643a9afad6
@@ -1,4 +1,4 @@
|
||||
import {ChatResponse, T} from "@simplex-chat/types"
|
||||
import {ChatEvent, ChatResponse, T} from "@simplex-chat/types"
|
||||
import * as api from "../src/api"
|
||||
import * as core from "../src/core"
|
||||
|
||||
@@ -30,6 +30,13 @@ describe("documented success responses", () => {
|
||||
await expect(chat.apiSetProfileAddress(1, true)).resolves.toEqual({updateSuccesses: 0, updateFailures: 0, changedContacts: []})
|
||||
})
|
||||
|
||||
it("apiSetUserDomain sets and removes the name", async () => {
|
||||
const chat = await chatWithResponse({type: "userProfileNoChange", user})
|
||||
await expect(chat.apiSetUserDomain(1, "calc.simplex")).resolves.toEqual(user)
|
||||
await expect(chat.apiSetUserDomain(1)).resolves.toEqual(user)
|
||||
expect(jest.mocked(core.chatSendCmd).mock.calls.map(([, cmd]) => cmd)).toEqual(["/_set domain 1 calc.simplex", "/_set domain 1"])
|
||||
})
|
||||
|
||||
it("apiReceiveFile reports a file cancelled by sender", async () => {
|
||||
const chat = await chatWithResponse({type: "rcvFileAcceptedSndCancelled", user, rcvFileTransfer: {}})
|
||||
await expect(chat.apiReceiveFile(3)).rejects.toThrow("file cancelled by sender")
|
||||
@@ -94,6 +101,15 @@ describe("startChat lifecycle", () => {
|
||||
await chat.stopChat()
|
||||
})
|
||||
|
||||
it("passes the chat api to event subscribers", async () => {
|
||||
const chat = await chatWithResponses({type: "chatStarted"}, {type: "chatStopped"})
|
||||
jest.mocked(core.chatRecvMsgWait).mockResolvedValueOnce({type: "hostConnected"} as ChatEvent)
|
||||
const subscriberChat = new Promise(resolve => chat.on("hostConnected", (_event, c) => resolve(c)))
|
||||
await chat.startChat()
|
||||
await expect(subscriberChat).resolves.toBe(chat)
|
||||
await chat.stopChat()
|
||||
})
|
||||
|
||||
it("receives with a 500 ms wait", async () => {
|
||||
const chat = await chatWithResponses()
|
||||
await chat.recvChatEvent()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {ChatEvent, T} from "@simplex-chat/types"
|
||||
import * as api from "../src/api"
|
||||
import {subscribeChatItems} from "../src/bot"
|
||||
import {run, subscribeChatItems} from "../src/bot"
|
||||
|
||||
type Handler = (evt: ChatEvent) => Promise<void>
|
||||
|
||||
@@ -40,6 +40,14 @@ describe("subscribeChatItems", () => {
|
||||
expect(calls).toEqual(["message:/unknown", "message:hello"])
|
||||
})
|
||||
|
||||
it("passes the chat api to handlers", async () => {
|
||||
const {bot, deliver} = fakeBot()
|
||||
const chats: api.ChatApi[] = []
|
||||
subscribeChatItems(bot, async (_ci, _content, chat) => { chats.push(chat) }, {help: async (_ci, _cmd, chat) => { chats.push(chat) }})
|
||||
await deliver([item("rcvMsgContent", "/help"), item("rcvMsgContent", "hello")])
|
||||
expect(chats).toEqual([bot, bot])
|
||||
})
|
||||
|
||||
it("ignores sent items", async () => {
|
||||
const {bot, deliver} = fakeBot()
|
||||
const calls: string[] = []
|
||||
@@ -48,3 +56,75 @@ describe("subscribeChatItems", () => {
|
||||
expect(calls).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe("run", () => {
|
||||
const address = {
|
||||
connLinkContact: {connFullLink: "full", connShortLink: "short"},
|
||||
addressSettings: {businessAddress: false, autoAccept: {acceptIncognito: false}},
|
||||
} as unknown as T.UserContactLink
|
||||
|
||||
function fakeChat(contactDomain?: T.SimplexDomainClaim) {
|
||||
const user = {userId: 1, profile: {displayName: "Old", fullName: "", contactDomain}} as unknown as T.User
|
||||
const chat = {
|
||||
on: jest.fn(),
|
||||
apiGetActiveUser: jest.fn().mockResolvedValue(user),
|
||||
startChat: jest.fn(),
|
||||
apiGetUserAddress: jest.fn().mockResolvedValue(address),
|
||||
apiSetAddressSettings: jest.fn(),
|
||||
apiSetUserDomain: jest.fn(async (_userId: number, domain?: string) => ({...user, profile: {...user.profile, contactDomain: domain && {domain}}})),
|
||||
apiUpdateProfile: jest.fn().mockResolvedValue({updateSuccesses: 0, updateFailures: 0}),
|
||||
}
|
||||
jest.spyOn(api.ChatApi, "init").mockResolvedValue(chat as unknown as api.ChatApi)
|
||||
return chat
|
||||
}
|
||||
|
||||
const runBot = (simplexDomain?: string | null, options = {}) =>
|
||||
run({profile: {displayName: "Calculator", fullName: ""}, simplexDomain, dbOpts: {type: "sqlite", filePrefix: "unused"}, options})
|
||||
|
||||
const updatedProfile = (chat: ReturnType<typeof fakeChat>) => chat.apiUpdateProfile.mock.calls[0][1]
|
||||
|
||||
beforeEach(() => jest.spyOn(console, "log").mockImplementation(() => {}))
|
||||
afterEach(() => jest.restoreAllMocks())
|
||||
|
||||
it("sets the configured SimpleX name", async () => {
|
||||
const chat = fakeChat()
|
||||
await runBot("Calc.simplex")
|
||||
expect(chat.apiSetUserDomain).toHaveBeenCalledWith(1, "calc.simplex")
|
||||
expect(updatedProfile(chat).contactDomain).toEqual({domain: "calc.simplex"})
|
||||
})
|
||||
|
||||
it("removes the SimpleX name set to null", async () => {
|
||||
const chat = fakeChat({domain: "calc.simplex"})
|
||||
await runBot(null)
|
||||
expect(chat.apiSetUserDomain).toHaveBeenCalledWith(1, undefined)
|
||||
expect(updatedProfile(chat).contactDomain).toBeUndefined()
|
||||
})
|
||||
|
||||
it("keeps the stored SimpleX name when it is not configured", async () => {
|
||||
const chat = fakeChat({domain: "calc.simplex"})
|
||||
await runBot()
|
||||
expect(chat.apiSetUserDomain).not.toHaveBeenCalled()
|
||||
expect(updatedProfile(chat).contactDomain).toEqual({domain: "calc.simplex"})
|
||||
})
|
||||
|
||||
it("keeps the SimpleX name when updating the profile", async () => {
|
||||
const chat = fakeChat({domain: "calc.simplex", proof: {presHeader: "header", signature: "signature"}})
|
||||
await runBot("calc.simplex")
|
||||
expect(chat.apiSetUserDomain).not.toHaveBeenCalled()
|
||||
expect(updatedProfile(chat).displayName).toBe("Calculator")
|
||||
expect(updatedProfile(chat).contactDomain).toEqual({domain: "calc.simplex"})
|
||||
})
|
||||
|
||||
it("continues when the SimpleX name cannot be set", async () => {
|
||||
const chat = fakeChat()
|
||||
chat.apiSetUserDomain.mockRejectedValue(new Error("simplexDomainNotReady"))
|
||||
await expect(runBot("calc.simplex")).resolves.toBeDefined()
|
||||
expect(updatedProfile(chat).contactDomain).toBeUndefined()
|
||||
})
|
||||
|
||||
it("does not change the SimpleX name without updateAddress", async () => {
|
||||
const chat = fakeChat()
|
||||
await runBot("calc.simplex", {updateAddress: false})
|
||||
expect(chat.apiSetUserDomain).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user