From 9dab429d0dbba86793740de5bd5e8e72e422be93 Mon Sep 17 00:00:00 2001 From: Aster Fialla Date: Thu, 19 Feb 2026 00:51:33 -0500 Subject: [PATCH] , updated tests for webhookHelper and removed error response when proxy is sent without content --- src/helpers/webhookHelper.js | 30 +++--- tests/helpers/webhookHelper.test.js | 141 +++++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 16 deletions(-) diff --git a/src/helpers/webhookHelper.js b/src/helpers/webhookHelper.js index 9aea380..23d9419 100644 --- a/src/helpers/webhookHelper.js +++ b/src/helpers/webhookHelper.js @@ -8,6 +8,7 @@ const name = 'PluralFlux Proxy Webhook'; /** * Replaces a proxied message with a webhook using the member information. + * @async * @param {Client} client - The fluxer.js client. * @param {Message} message - The full message object. * @throws {Error} When the proxy message is not in a server. @@ -16,7 +17,7 @@ wh.sendMessageAsMember = async function(client, message) { const attachmentUrl = message.attachments.size > 0 ? message.attachments.first().url : null; const proxyMatch = await messageHelper.parseProxyTags(message.author.id, message.content, attachmentUrl).catch(e =>{throw e}); // If the message doesn't match a proxy, just return. - if (!proxyMatch || !proxyMatch.member) { + if (!proxyMatch || !proxyMatch.member || (proxyMatch.message.length === 0 && !proxyMatch.hasAttachment) ) { return; } // If the message does match a proxy but is not in a guild server (ex: in the Bot's DMs) @@ -31,6 +32,7 @@ wh.sendMessageAsMember = async function(client, message) { /** * Replaces a proxied message with a webhook using the member information. + * @async * @param {Client} client - The fluxer.js client. * @param {Message} message - The message to be deleted. * @param {string} text - The text to send via the webhook. @@ -38,26 +40,30 @@ wh.sendMessageAsMember = async function(client, message) { * @throws {Error} When there's no message to send. */ wh.replaceMessage = async function(client, message, text, member) { + // attachment logic is not relevant yet, text length will always be over 0 right now if (text.length > 0 || message.attachments.size > 0) { const channel = client.channels.get(message.channelId); const webhook = await wh.getOrCreateWebhook(client, channel).catch((e) =>{throw e}); const username = member.displayname ?? member.name; - await webhook.send({content: text, username: username, avatar_url: member.propic}).catch(async(e) => { - const returnedBuffer = messageHelper.returnBufferFromText(text); - await webhook.send({content: returnedBuffer.text, username: username, avatar_url: member.propic, files: [{ name: 'text.pdf', data: returnedBuffer.file }] - }) - console.error(e); - }); + if (text.length > 0) { + await webhook.send({content: text, username: username, avatar_url: member.propic}).catch(async(e) => { + const returnedBuffer = messageHelper.returnBufferFromText(text); + await webhook.send({content: returnedBuffer.text, username: username, avatar_url: member.propic, files: [{ name: 'text.txt', data: returnedBuffer.file }] + }) + console.error(e); + }); + } + if (message.attachments.size > 0) { + // Not implemented yet + } + await message.delete(); } - else { - throw new Error(enums.err.NO_MESSAGE_SENT_WITH_PROXY); - } } /** * Gets or creates a webhook. - * + * @async * @param {Client} client - The fluxer.js client. * @param {Channel} channel - The channel the message was sent in. * @returns {Webhook} A webhook object. @@ -75,7 +81,7 @@ wh.getOrCreateWebhook = async function(client, channel) { /** * Gets an existing webhook. - * + * @async * @param {Client} client - The fluxer.js client. * @param {Channel} channel - The channel the message was sent in. * @returns {Webhook} A webhook object. diff --git a/tests/helpers/webhookHelper.test.js b/tests/helpers/webhookHelper.test.js index 7c645a4..23a3aee 100644 --- a/tests/helpers/webhookHelper.test.js +++ b/tests/helpers/webhookHelper.test.js @@ -5,7 +5,8 @@ const {messageHelper} = require("../../src/helpers/messageHelper.js"); jest.mock('../../src/helpers/messageHelper.js', () => { return {messageHelper: { parseProxyTags: jest.fn(), - returnBuffer: jest.fn() + returnBuffer: jest.fn(), + returnBufferFromText: jest.fn(), }} }) @@ -14,16 +15,18 @@ const {enums} = require("../../src/enums"); describe('webhookHelper', () => { - const client = {}; - beforeEach(() => { jest.resetModules(); jest.clearAllMocks(); }) describe(`sendMessageAsMember`, () => { + const client = {}; const content = "hi" - const attachments = new Map(); + const attachments = { + size: 0, + first: () => {} + } const message = { client, content: content, @@ -64,6 +67,7 @@ describe('webhookHelper', () => { expect(res).toBeUndefined(); expect(messageHelper.parseProxyTags).toHaveBeenCalledTimes(1); expect(messageHelper.parseProxyTags).toHaveBeenCalledWith(message.author.id, content, null); + expect(webhookHelper.replaceMessage).not.toHaveBeenCalled(); }) }) @@ -94,6 +98,7 @@ describe('webhookHelper', () => { return webhookHelper.sendMessageAsMember(client, message).catch((res) => { // Assert expect(res).toEqual(new Error(enums.err.NOT_IN_SERVER)); + expect(webhookHelper.replaceMessage).not.toHaveBeenCalled(); }) }) @@ -112,11 +117,139 @@ describe('webhookHelper', () => { }) }) + test('if message matches member proxy and sent in a guild channel and no attachment, calls replace message', async() => { + // Arrange + message.guildId = '123'; + proxyMessage.hasAttachment = false; + messageHelper.parseProxyTags.mockResolvedValue(proxyMessage); + jest.spyOn(webhookHelper, 'replaceMessage').mockResolvedValue(); + // Act + return webhookHelper.sendMessageAsMember(client, message).then((res) => { + // Assert + expect(message.reply).not.toHaveBeenCalled(); + expect(webhookHelper.replaceMessage).toHaveBeenCalledTimes(1); + expect(webhookHelper.replaceMessage).toHaveBeenCalledWith(client, message, proxyMessage.message, proxyMessage.member); + }) + }) + test('if replace message throws error, throw same error', async() => { + // Arrange + message.guildId = '123'; + messageHelper.parseProxyTags.mockResolvedValue(proxyMessage); + jest.spyOn(webhookHelper, 'replaceMessage').mockImplementation(() => {throw new Error("error")}); + // Act + return webhookHelper.sendMessageAsMember(client, message).catch((res) => { + // Assert + expect(message.reply).not.toHaveBeenCalled(); + expect(webhookHelper.replaceMessage).toHaveBeenCalledTimes(1); + expect(webhookHelper.replaceMessage).toHaveBeenCalledWith(client, message, proxyMessage.message, proxyMessage.member); + expect(res).toEqual(new Error('error')); + }) + }) }) describe(`replaceMessage`, () => { + const channelId = '123'; + const authorId = '456'; + const guildId = '789'; + const text = "hello"; + const client = { + channels: { + get: jest.fn().mockReturnValue(channelId) + } + } + const member = {proxy: "--text", name: 'somePerson', displayname: "Some Person", propic: 'oya.png'}; + const attachments= { + size: 1, + first: () => {return channelId;} + }; + const message = { + client, + channelId: channelId, + content: text, + attachments: attachments, + author: { + id: authorId + }, + guild: { + guildId: guildId + }, + reply: jest.fn(), + delete: jest.fn() + } + const webhook = { + send: async() => jest.fn().mockResolvedValue() + } + + test('does not call anything if text is 0 or message has no attachments', async() => { + // Arrange + const emptyText = '' + const noAttachments = { + size: 0, + first: () => {} + } + message.attachments = noAttachments; + jest.spyOn(webhookHelper, 'getOrCreateWebhook').mockResolvedValue(webhook); + // Act + return webhookHelper.replaceMessage(client, message, emptyText, member).then(() => { + expect(webhookHelper.getOrCreateWebhook).not.toHaveBeenCalled(); + expect(message.delete).not.toHaveBeenCalled(); + }) + }) + + test('calls getOrCreateWebhook and message.delete with correct arguments if text >= 0', async() => { + // Arrange + message.attachments = { + size: 0, + first: () => { + } + }; + jest.spyOn(webhookHelper, 'getOrCreateWebhook').mockResolvedValue(webhook); + // Act + return webhookHelper.replaceMessage(client, message, text, member).then((res) => { + // Assert + expect(webhookHelper.getOrCreateWebhook).toHaveBeenCalledTimes(1); + expect(webhookHelper.getOrCreateWebhook).toHaveBeenCalledWith(client, channelId); + expect(message.delete).toHaveBeenCalledTimes(1); + expect(message.delete).toHaveBeenCalledWith(); + }) + }) + + test('calls getOrCreateWebhook and message.delete with correct arguments if attachments exist', async() => { + // Arrange + const emptyText = '' + jest.spyOn(webhookHelper, 'getOrCreateWebhook').mockResolvedValue(webhook); + // Act + return webhookHelper.replaceMessage(client, message, emptyText, member).then((res) => { + // Assert + expect(webhookHelper.getOrCreateWebhook).toHaveBeenCalledTimes(1); + expect(webhookHelper.getOrCreateWebhook).toHaveBeenCalledWith(client, channelId); + expect(message.delete).toHaveBeenCalledTimes(1); + expect(message.delete).toHaveBeenCalledWith(); + }) + }) + + test('calls returnBufferFromText and console error if webhook.send returns error', async() => { + // Arrange + const file = Buffer.from(text, 'utf-8'); + const returnedBuffer = {text: text, file: file}; + const expected2ndSend = {content: returnedBuffer.text, username: member.displayname, avatar_url: member.propic, files: [{name: 'text.txt', data: returnedBuffer.file}]}; + jest.mock('console', () => ({error: jest.fn()})); + jest.spyOn(webhookHelper, 'getOrCreateWebhook').mockResolvedValue(webhook); + webhook.send = jest.fn().mockImplementationOnce(async() => {throw new Error('error')}); + messageHelper.returnBufferFromText = jest.fn().mockResolvedValue(returnedBuffer); + // Act + return webhookHelper.replaceMessage(client, message, text, member).catch((res) => { + // Assert + expect(messageHelper.returnBufferFromText).toHaveBeenCalledTimes(1); + expect(messageHelper.returnBufferFromText).toHaveBeenCalledWith(text); + expect(webhook.send).toHaveBeenCalledTimes(2); + expect(webhook.send).toHaveBeenNthCalledWith(2, expected2ndSend); + expect(console.error).toHaveBeenCalledTimes(1); + expect(console.error).toHaveBeenCalledWith(new Error('error')); + }) + }) }) describe(`getOrCreateWebhook`, () => {