diff --git a/src/clientfactory.ts b/src/clientfactory.ts index ec842ecc32a19ff3d92a34aae766e14ed9f0beb1..7055ccf0d03390aa6bec368e0744c2d846147e9a 100644 --- a/src/clientfactory.ts +++ b/src/clientfactory.ts @@ -17,7 +17,7 @@ export class DiscordClientFactory { this.store = store; } - public init(): Promise<null> { + public async init(): Promise<void> { if (this.config === undefined) { return Promise.reject("Client config not supplied."); } @@ -28,12 +28,12 @@ export class DiscordClientFactory { sync: true, messageCacheLifetime: 5, })); - this.botClient.login(this.config.botToken); - return this.botClient.onAsync("ready") - .timeout(READY_TIMEOUT, "Bot timed out waiting for ready.") - .catch((err) => { - log.error("ClientFactory", "Could not login as the bot user. This is bad!", err); - throw err; + return Bluebird.all([ + this.botClient.onAsync("ready").timeout(READY_TIMEOUT, "Bot timed out waiting for ready."), + this.botClient.login(this.config.botToken), + ]).then(() => { return; }).catch((err) => { + log.error("ClientFactory", "Could not login as the bot user. This is bad!", err); + throw err; }); } @@ -44,15 +44,15 @@ export class DiscordClientFactory { messageCacheLifetime: 5, }); return new Bluebird<string>((resolve, reject) => { - client.login(token).catch(reject); client.on("ready", () => { const id = client.user.id; client.destroy(); resolve(id); }); + client.login(token).catch(reject); }).timeout(READY_TIMEOUT).catch((err: Error) => { log.warn("ClientFactory", "Could not login as a normal user. '%s'", err.message); - throw Error("Could not retrive ID"); + throw Error("Could not retrieve ID"); }); } @@ -81,7 +81,8 @@ export class DiscordClientFactory { this.clients.set(userId, client); return client; } catch (err) { - log.warn("ClientFactory", `Could not log ${userId} in.`, err); + log.warn("ClientFactory", `Could not log ${userId} in. Returning bot user for now.`, err); + return this.botClient; } } } diff --git a/test/mocks/discordclient.ts b/test/mocks/discordclient.ts index 71ffef63a1f37141798c36b13941f90a4225c797..d431ebf1dd0b0a768d691aeeac08560148ef8a24 100644 --- a/test/mocks/discordclient.ts +++ b/test/mocks/discordclient.ts @@ -6,7 +6,7 @@ export class MockDiscordClient { public guilds = new MockCollection<string, MockGuild>(); public user: MockUser; private testLoggedIn: boolean = false; - private testCallbacks: Array<() => void> = []; + private testCallbacks: Map<string, () => void> = new Map(); constructor() { const channels = [ @@ -31,13 +31,19 @@ export class MockDiscordClient { } public on(event: string, callback: () => void) { - if (event === "ready") { - this.testCallbacks[0] = callback; - } + this.testCallbacks.set(event, callback); } - public login(token: string) { + public async login(token: string): Promise<void> { + if (token !== "passme") { + throw new Error("Mock Discord Client only logins with the token 'passme'"); + } this.testLoggedIn = true; - this.testCallbacks[0](); + if (this.testCallbacks.has("ready")) { + this.testCallbacks.get("ready")(); + } + return; } + + public destroy() { } // no-op } diff --git a/test/test_clientfactory.ts b/test/test_clientfactory.ts new file mode 100644 index 0000000000000000000000000000000000000000..721962646a810a2b40af67b1e1a0551c75bc0d31 --- /dev/null +++ b/test/test_clientfactory.ts @@ -0,0 +1,110 @@ +import * as Chai from "chai"; +import * as ChaiAsPromised from "chai-as-promised"; +import * as Proxyquire from "proxyquire"; +import {DiscordBridgeConfigAuth} from "../src/config"; +import {MockDiscordClient} from "./mocks/discordclient"; +import * as log from "npmlog"; + +Chai.use(ChaiAsPromised); +const expect = Chai.expect; + +const DiscordClientFactory = Proxyquire("../src/clientfactory", { + "discord.js": { Client: require("./mocks/discordclient").MockDiscordClient }, +}).DiscordClientFactory; + +const STORE = { + get_user_discord_ids: (userid: string) => { + if (userid === "@valid:localhost") { + return Promise.resolve(["12345"]); + } else if (userid === "@invalid:localhost") { + return Promise.resolve(["1234555"]); + } + return Promise.resolve([]); + }, + get_token: (discordid: string) => { + if (discordid === "12345") { + return Promise.resolve("passme"); + } else if (discordid === "1234555") { + return Promise.resolve("failme"); + } + return Promise.reject("Token not found"); + }, +}; + +describe("ClientFactory", () => { + describe("init", () => { + it ("should start successfully", () => { + const config = new DiscordBridgeConfigAuth(); + config.botToken = "passme"; + const cf = new DiscordClientFactory(null, config); + return expect(cf.init()).to.eventually.be.fulfilled; + }); + it ("should fail if a config is not supplied", () => { + log.level = "silent"; + const cf = new DiscordClientFactory(null); + return expect(cf.init()).to.eventually.be.rejected; + }); + it ("should fail if the bot fails to connect", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + config.botToken = "failme"; + const cf = new DiscordClientFactory(null, config); + return expect(cf.init()).to.eventually.be.rejected; + }); + }); + describe("getDiscordId", () => { + it("should fetch id successfully", () => { + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(null); + return expect(cf.getDiscordId("passme")).to.eventually.equal("12345"); + }); + it("should fail if the token is not recognised", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(null); + return expect(cf.getDiscordId("failme")).to.eventually.be.rejected; + }); + }); + describe("getClient", () => { + it("should fetch bot client successfully", () => { + const config = new DiscordBridgeConfigAuth(); + config.botToken = "passme"; + const cf = new DiscordClientFactory(null, config); + cf.botClient = 1; + return expect(cf.getClient()).to.eventually.equal(cf.botClient); + }); + it("should return cached client", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(null); + cf.clients.set("@user:localhost", "testclient"); + return expect(cf.getClient("@user:localhost")).to.eventually.equal("testclient"); + }); + it("should fetch bot client if userid doesn't match", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(STORE); + cf.botClient = 1; + return expect(cf.getClient("@user:localhost")).to.eventually.equal(cf.botClient); + }); + it("should fetch user client if userid matches", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(STORE); + return cf.getClient("@valid:localhost").then((client) => { + expect(client).is.not.null; + expect(cf.clients.has("@valid:localhost")).to.be.true; + }); + }); + it("should fail if the user client cannot log in", () => { + log.level = "silent"; + const config = new DiscordBridgeConfigAuth(); + const cf = new DiscordClientFactory(STORE); + cf.botClient = 1; + return cf.getClient("@invalid:localhost").then((client) => { + expect(client).to.equal(cf.botClient); + expect(cf.clients.has("@invalid:localhost")).to.be.false; + }); + }); + }); +}); diff --git a/test/test_discordbot.ts b/test/test_discordbot.ts index c11d8a5e9e1e8fd86acfe93112805684347cd4a7..95855e72dd60790d02f1a5682af28348c05351e9 100644 --- a/test/test_discordbot.ts +++ b/test/test_discordbot.ts @@ -25,7 +25,7 @@ const mockBridge = { }; }, getIntentFromLocalpart: (localpart: string) => { - return{ + return { sendTyping: (room: string, isTyping: boolean) => { return; },