12 KiB
SlackBridge Manual Test Plan
The SlackBridge is a bi-directional bridge between a Rocket.Chat workspace and one or more Slack workspaces — each token line in the SlackBridge settings gets its own connection and adapter. It has no automated end-to-end coverage: exercising it requires a real Slack workspace, a real bot installation, and a human watching both sides at once. This document is the checklist to walk through when touching the bridge.
Scope: the matrices below assume a single bridged Slack workspace — configure exactly one token per setting while running them. Bridging several workspaces at once is a supported configuration that this plan does not cover; see Coverage gaps.
Code lives in apps/meteor/server/bridges/slack/ —
SlackAdapter.ts handles Slack → Rocket.Chat, RocketAdapter.ts handles Rocket.Chat → Slack
(hooked in through the afterSaveMessage, afterDeleteMessage, afterSetReaction and
afterUnsetReaction callbacks). Settings are declared in
apps/meteor/server/settings/slackbridge.ts.
Setup
Configure the bridge in Admin → Settings → SlackBridge:
| Setting | Notes |
|---|---|
SlackBridge_Enabled |
Master switch. Must be on. |
SlackBridge_UseLegacy |
Chooses the connection mode — see below. Run the matrices in the mode you are testing. |
SlackBridge_APIToken |
Legacy mode only (RTM). |
SlackBridge_BotToken, SlackBridge_SigningSecret, SlackBridge_AppToken |
App mode only (Bolt / Socket Mode). |
SlackBridge_Out_Enabled |
Required for anything to flow Rocket.Chat → Slack. |
SlackBridge_Out_All / SlackBridge_Out_Channels |
Which Rocket.Chat rooms are bridged out. |
SlackBridge_Reactions_Enabled |
Gates reaction propagation in both directions. |
SlackBridge_AliasFormat |
Optional, Slack → Rocket.Chat only. %s is the Slack username; test with %s (via Slack). |
SlackBridge_FileUpload_Enabled |
Gates file transfer. |
Two connection modes exist and they use different Slack event plumbing, so a regression can appear in one and not the other. Run the full matrix in both when changing anything in the connect/event-subscription path:
- Legacy (
SlackBridge_UseLegacy: true) — RTM connection with an API token. - App (
SlackBridge_UseLegacy: false) — Slack app using bot token, signing secret and app token.
You also need:
- A Slack workspace where you can create channels and install/invite the bot (referred to below as rocketbot).
- At least one channel that exists on both sides with rocketbot in it, and one that exists on both sides without rocketbot in it. Several cases below hinge on that difference.
- A second Slack user, if possible — some behaviors only show up when the message author is not the same account as the bot.
Watch SlackBridge logs (slackLogger / rocketLogger) while testing; several expected
failures are only visible there.
How to read the matrices
- Origin — where the message being acted on was originally posted.
- Action performed on — the side where the tester performs the action.
- Every matrix must also be repeated on a channel that rocketbot is not a member of. Nothing should propagate in either direction for those channels, and nothing should error.
Sending messages
| # | Origin | Action performed on | Expected result |
|---|---|---|---|
| 1 | Slack | Slack | Message appears in the linked Rocket.Chat room, under the alias SlackBridge_AliasFormat produces. |
| 2 | Rocket.Chat | Rocket.Chat | Message appears in the linked Slack channel, posted by rocketbot with the sender's username and avatar. |
SlackBridge_AliasFormat only affects case 1: addAliasToMsg sets alias on the Rocket.Chat
message, so with %s (via Slack) a message from Slack user alice shows as alice (via Slack).
Case 2 carries the sender's identity through chat.postMessage's username/icon_url and ignores
the setting entirely. Set the format, run case 1 with it set and again with it empty, then restore
the original value before moving on — the later matrices assume the workspace's normal setup.
Repeat both on a channel without rocketbot: neither message crosses over.
Editing messages
Slack does not allow an app to edit messages it did not post, and it does not allow humans to edit bot messages. Two of the four cases are therefore expected failures — they are listed because "nothing crashes and the local side stays consistent" is the requirement.
| # | Origin | Action performed on | Expected result |
|---|---|---|---|
| 1 | Slack | Slack | Edit propagates to Rocket.Chat. |
| 2 | Rocket.Chat | Rocket.Chat | Edit propagates to Slack. |
| 3 | Slack | Rocket.Chat | Expected failure. Rocket.Chat shows the edit; Slack is unchanged. chat.update is rejected because the message is not the bot's. |
| 4 | Rocket.Chat | Slack | Expected failure. Slack does not even offer the edit affordance for a bot message. |
Repeat on a channel without rocketbot: edits stay local on both sides.
Deleting messages
Case 3 needs care about who deletes. A Rocket.Chat-origin message is authored on Slack by rocketbot, and Slack offers no delete affordance for an app's message to a regular member, so pick one of:
- Delete it from the Slack UI as a workspace owner or admin — they can delete any message, including an app's.
- Call
chat.deletewith the very token the bridge is configured with, so the caller is rocketbot itself:SlackBridge_APITokenin legacy/RTM mode,SlackBridge_BotTokenin app/Socket Mode. Any other token fails withcant_delete_message, which is case 4's failure, not case 3's.
Both routes emit the same message_deleted event, so either is a valid way to run the case.
| # | Origin | Action performed on | Expected result |
|---|---|---|---|
| 1 | Slack | Slack | Deletion propagates to Rocket.Chat. |
| 2 | Rocket.Chat | Rocket.Chat | Deletion propagates to Slack. |
| 3 | Rocket.Chat | Slack | Deletion propagates to Rocket.Chat — deleted as a workspace admin or via chat.delete with rocketbot's own token, per the note above. |
| 4 | Slack | Rocket.Chat | Expected failure. The message is deleted in Rocket.Chat only; Slack keeps it, since chat.delete cannot remove another user's message. |
Repeat on a channel without rocketbot: deletions stay local on both sides.
Reactions
Requires SlackBridge_Reactions_Enabled. Reactions sent to Slack are added by the bot account,
so on the Slack side every Rocket.Chat reaction shows up as rocketbot's reaction regardless of
who actually reacted.
| # | Origin | Action performed on | Expected result |
|---|---|---|---|
| 1 | Slack | Slack | Reaction appears on the Rocket.Chat message. |
| 2 | Rocket.Chat | Slack | Reaction appears on the Rocket.Chat message. |
| 3 | Rocket.Chat | Rocket.Chat | Reaction appears on the Slack message (as rocketbot). |
| 4 | Slack | Rocket.Chat | Reaction appears on the Slack message (as rocketbot). |
Also check removal of each reaction, and confirm a reaction is not echoed back to its origin (the bridge de-duplicates through its reactions map — a double-count means that broke).
Repeat on a channel without rocketbot: reactions stay local.
SlackBridge_Reactions_Enabled toggle
| Setting state | Expected result |
|---|---|
| Disabled | React to both a Slack-origin and a Rocket.Chat-origin message from both sides — nothing propagates, no errors. |
| Enabled | Re-run the same reactions — they propagate as in the matrix above, without restarting the server. |
Channel lifecycle
These cases cover how the bridge reacts to channels appearing, disappearing, and the bot joining or leaving. Send a message from each side after every step and verify propagation.
Channel exists on both sides, rocketbot not in the Slack channel
- Confirm nothing propagates in either direction.
- Invite rocketbot to the Slack channel.
- Send from Slack and from Rocket.Chat — both directions now work.
Channel exists on Rocket.Chat only
- Create the matching channel in Slack and invite rocketbot.
- Send from Rocket.Chat — it reaches Slack.
- Send from Slack — it reaches Rocket.Chat.
Channel exists on Slack only
- Invite rocketbot to the Slack channel.
- Send from Slack — the Rocket.Chat channel is created and receives the message.
- Send from Rocket.Chat — it reaches Slack.
Channel exists on both sides with rocketbot
- Delete the Rocket.Chat channel, then send from Slack — behaves like the "Slack only" case above (the channel is recreated).
- Remove rocketbot from the Slack channel, then send from Slack and from Rocket.Chat — nothing propagates in either direction, and no errors are logged.
Coverage gaps
The matrices above are the historical manual suite and deliberately mirror it. They do not cover, and it is worth checking manually when relevant:
- File uploads (
SlackBridge_FileUpload_Enabled). - Slack history import (
/slackbridge-import,slackbridge_import.server.ts). - Threads (
thread_tsmapping inpostMessage). - Private channels and DMs.
SlackBridge_ExcludeBotnamesfiltering.- The Remove Channel Links admin action (
SlackBridge_Remove_Channel_Links). - Multiple Slack workspaces bridged at once (one token per line in each token setting).