slackapi / deno-slack-sdk

SDK for building Run on Slack apps using Deno

Home Page:https://api.slack.com/automation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[QUERY] Running a test with the recommended setup results in 405 status code error

hgg opened this issue · comments

Question

Why do I get a 405 error when running a test for a function that calls

const userGroups = await client.usergroups.list();

when the function is mocked like so

mf.mock("GET@/api/usergroups.list", (_args) => {
  return new Response(
    `{"ok": true, "userGroups": [{ handle: "admin", id: "S0321TZR7" }]}`,
  );
});

Test output

image

Context

I need to create a workflow that sends a message and tags a slack group on that message. Since tagging groups is not supported out-of-the-box, I thought about creating a custom function that would get the name of the group to be tagged as an input and, using the usergroups.list API, get the proper group ID and tag it on the message.

Full code

Function definition

import { DefineFunction, Schema, SlackFunction } from "deno-slack-sdk/mod.ts";

export const AddTagFunction = DefineFunction({
callback_id: "add_tag_function",
title: "Adds Group Tag to Message",
description:
  "Replaces the text-version group tag with a proper slack tag for the same group",
source_file: "functions/add_tag_function.ts",
input_parameters: {
  properties: {
    message: {
      type: Schema.types.string,
      description:
        "Message to be posted. Must contain `@group` so that it can be replaced in the final message.",
    },
    group_display_name: {
      type: Schema.types.string,
      description:
        "Display name of the group to be tagged. A tag for this group will replace `@group` in the message.",
    },
  },
  required: ["message", "group_display_name"],
},
output_parameters: {
  properties: {
    updatedMsg: {
      type: Schema.types.string,
      description: "Updated message to be posted",
    },
  },
  required: ["updatedMsg"],
},
});

export default SlackFunction(
AddTagFunction,
async ({ inputs, client }) => {
  // Retrieve the list of user groups
  const userGroups = await client.usergroups.list();

  if (!userGroups.ok) {
    // If there was an error retrieving user groups, log an error and return the original message
    console.error("Error retrieving user groups:", userGroups.error);
    return { outputs: { updatedMsg: inputs.message } };
  }

  // Find the user group with the specified display name
  const userGroup = userGroups.userGroups.find((
    group: { handle: string; id: string },
  ) => group.handle === inputs.group_display_name);

  if (!userGroup) {
    // If the user group is not found, log an error and return the original message
    console.error("User group not found:", inputs.group_display_name);
    return { outputs: { updatedMsg: inputs.message } };
  }

  // Generate the user group tag
  const userGroupTag = `<!subteam^${userGroup.id}>`;

  // Replace "@group" with the user group tag in the message
 // I know this doesn't likely tag the group. This is just an intermediary version before I actually send the message through the API.
  const updatedMsg = inputs.message.replace("@group", userGroupTag);

  // Return the updated message
  return { outputs: { updatedMsg } };
},
);

Test

import { SlackFunctionTester } from "deno-slack-sdk/mod.ts";
import { assertEquals } from "std/assert/assert_equals.ts";
import AddTagFunction from "./add_tag_function.ts";
import * as mf from "mock-fetch/mod.ts";

const { createContext } = SlackFunctionTester("add_tag_function");

// Replaces globalThis.fetch with the mocked copy
mf.install();

// Shared mocks can be defined at the top level of tests
mf.mock("GET@/api/usergroups.list", (_args) => {
  return new Response(
    `{"ok": true, "userGroups": [{ handle: "admins", id: "S0321TZR7" }]}`,
  );
});

Deno.test("AddGroupTag returns the original message with the proper group tag", async () => {
  const inputs = {
    message: "Testing message where @group is tagged.",
    group_display_name: "admins",
  };

  const { outputs, error } = await AddTagFunction(createContext({ inputs }));

  assertEquals(error, undefined);
  assertEquals(
    outputs?.updatedMsg,
    "Testing message where <!subteam^S0321TZR7> is tagged.",
  );
});

Environment

# Slack SDK & API
"deno-slack-sdk/": "https://deno.land/x/deno_slack_sdk@2.6.0/",
"deno-slack-api/": "https://deno.land/x/deno_slack_api@2.2.0/",

# Deno Version
deno 1.41.0 (release, aarch64-apple-darwin)
v8 12.1.285.27
typescript 5.3.3

# Machine
ProductName:            macOS
ProductVersion:         14.3.1
BuildVersion:           23D60

Hi @hgg thanks for writing in 💯

The following works on my end

Deno.test("Test mocking behavior", async () => {
  mf.install();
  mf.mock("POST@/api/usergroups.list", () => {
    return new Response(
      `{"ok": true, "userGroups": [{ "handle": "admin", "id": "S0321TZR7" }]}`,
      {
        status: 200,
      },
    );
  });
  const client = SlackAPI("test");
  const userGroups = await client.usergroups.list();

  assert(userGroups.ok);
});
  • Almost all HTTP requests sent to the Slack API are POST, the example above seems to be using GET
  • The payload passed to the mock must be a valid JSON string, ensure no " chars are missing

Let me know if this helps

Yes! That worked @WilliamBergamin. Thank you very much for this 🙏🏼