diff --git a/test/mocks/message.ts b/test/mocks/message.ts
index 0c81f040eb4553457ccbbf873f94caa384c7bf7e..a022939e2b38c2bab3e558dc22f8bf512a53352e 100644
--- a/test/mocks/message.ts
+++ b/test/mocks/message.ts
@@ -1,10 +1,12 @@
 import * as Discord from "discord.js";
 import { MockUser } from "./user";
+import { MockCollection } from "./collection";
 
 // we are a test file and thus need those
 /* tslint:disable:no-unused-expression max-file-line-count no-any */
 
 export class MockMessage {
+    public attachments = new MockCollection<string, any>();
     public embeds: any[] = [];
     public content = "";
     public channel: Discord.TextChannel | undefined;
diff --git a/test/test_discordbot.ts b/test/test_discordbot.ts
index 2e7bb00dadfcd3742e5cc05f31351dcf243da14f..f936295a785a138f70ac310ed5f8dca36d119357 100644
--- a/test/test_discordbot.ts
+++ b/test/test_discordbot.ts
@@ -8,6 +8,7 @@ import { MockMember } from "./mocks/member";
 import { DiscordBot } from "../src/bot";
 import { MockDiscordClient } from "./mocks/discordclient";
 import { MockMessage } from "./mocks/message";
+import { Util } from "../src/util";
 
 // we are a test file and thus need those
 /* tslint:disable:no-unused-expression max-file-line-count no-any */
@@ -46,6 +47,14 @@ const mockBridge = {
 
 const modDiscordBot = Proxyquire("../src/bot", {
     "./clientfactory": require("./mocks/discordclientfactory"),
+    "./util": {
+        Util: {
+            AsyncForEach: Util.AsyncForEach,
+            UploadContentFromUrl: async () => {
+                return {mxcUrl: "uploaded"};
+            },
+        },
+    },
 });
 describe("DiscordBot", () => {
     let discordBot;
@@ -103,6 +112,169 @@ describe("DiscordBot", () => {
             await discordBot.LookupRoom("123", "321");
         });
     });
+    describe("OnMessage()", () => {
+        let SENT_MESSAGE = false;
+        let MARKED = -1;
+        let HANDLE_COMMAND = false;
+        let ATTACHMENT = {} as any;
+        let MSGTYPE = "";
+        function getDiscordBot() {
+            SENT_MESSAGE = false;
+            MARKED = -1;
+            HANDLE_COMMAND = false;
+            ATTACHMENT = {};
+            MSGTYPE = "";
+            const discord = new modDiscordBot.DiscordBot(
+                config,
+                mockBridge,
+            );
+            discord.bot = { user: { id: "654" } };
+            discord.provisioner = {
+                HasPendingRequest: (chan) => true,
+                MarkApproved: async (chan, member, approved) => {
+                    MARKED = approved ? 1 : 0;
+                    return approved;
+                },
+            };
+            discord.GetIntentFromDiscordMember = (_) => {return {
+                sendMessage: async (room, msg) => {
+                    SENT_MESSAGE = true;
+                    if (msg.info) {
+                        ATTACHMENT = msg.info;
+                    }
+                    MSGTYPE = msg.msgtype;
+                    return {
+                        event_id: "$fox:localhost",
+                    };
+                },
+            }; };
+            discord.userSync = {
+                OnUpdateUser: async (user) => { },
+            };
+            discord.channelSync = {
+                GetRoomIdsFromChannel: async (chan) => ["!asdf:localhost"],
+            };
+            discord.roomHandler = {
+                HandleDiscordCommand: async (msg) => { HANDLE_COMMAND = true; },
+            };
+            discord.store = {
+                Insert: async (_) => { },
+            };
+            return discord;
+        }
+        it("ignores own messages", async () => {
+            discordBot = getDiscordBot();
+            const guild: any = new MockGuild("123", []);
+            const author = new MockMember("654", "TestUsername");
+            guild._mockAddMember(author);
+            const channel = new Discord.TextChannel(guild, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.author = author;
+            msg.content = "Hi!";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(SENT_MESSAGE, false);
+        });
+        it("accepts !approve", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.content = "!approve";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MARKED, 1);
+        });
+        it("denies !deny", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.content = "!deny";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MARKED, 0);
+        });
+        it("Passes on !matrix commands", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.content = "!matrix test";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(HANDLE_COMMAND, true);
+        });
+        it("skips empty messages", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.content = "";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(SENT_MESSAGE, false);
+        });
+        it("sends normal messages", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.content = "Foxies are amazing!";
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(SENT_MESSAGE, true);
+        });
+        it("uploads images", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.attachments.set("1234", {
+                filename: "someimage.png",
+                filesize: 42,
+                height: 0,
+                url: "asdf",
+                width: 0,
+            });
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MSGTYPE, "m.image");
+            Chai.assert.equal(ATTACHMENT.mimetype, "image/png");
+        });
+        it("uploads videos", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.attachments.set("1234", {
+                filename: "foxes.mov",
+                filesize: 42,
+                height: 0,
+                url: "asdf",
+                width: 0,
+            });
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MSGTYPE, "m.video");
+            Chai.assert.equal(ATTACHMENT.mimetype, "video/quicktime");
+        });
+        it("uploads audio", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.attachments.set("1234", {
+                filename: "meow.mp3",
+                filesize: 42,
+                height: 0,
+                url: "asdf",
+                width: 0,
+            });
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MSGTYPE, "m.audio");
+            Chai.assert.equal(ATTACHMENT.mimetype, "audio/mpeg");
+        });
+        it("uploads other files", async () => {
+            discordBot = getDiscordBot();
+            const channel = new Discord.TextChannel({} as any, {} as any);
+            const msg = new MockMessage(channel) as any;
+            msg.attachments.set("1234", {
+                filename: "meow.zip",
+                filesize: 42,
+                height: 0,
+                url: "asdf",
+                width: 0,
+            });
+            await discordBot.OnMessage(msg);
+            Chai.assert.equal(MSGTYPE, "m.file");
+            Chai.assert.equal(ATTACHMENT.mimetype, "application/zip");
+        });
+    });
     describe("OnMessageUpdate()", () => {
         it("should return on an unchanged message", async () => {
             discordBot = new modDiscordBot.DiscordBot(
@@ -232,7 +404,4 @@ describe("DiscordBot", () => {
     //     return assert.isFulfilled(discordBot.OnTyping( {id: "321"}, {id: "12345"}, true));
     //   });
     // });
-    // describe("OnMessage()", () => {
-    //
-    // });
 });