Skip to content

Commit 52b93ed

Browse files
authored
fix(Slack Node): Sort messages manually (#21822)
1 parent 4319da6 commit 52b93ed

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

packages/nodes-base/nodes/Slack/Slack.node.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class Slack extends VersionedNodeType {
1313
group: ['output'],
1414
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
1515
description: 'Consume Slack API',
16-
defaultVersion: 2.3,
16+
defaultVersion: 2.4,
1717
};
1818

1919
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
@@ -22,6 +22,7 @@ export class Slack extends VersionedNodeType {
2222
2.1: new SlackV2(baseDescription),
2323
2.2: new SlackV2(baseDescription),
2424
2.3: new SlackV2(baseDescription),
25+
2.4: new SlackV2(baseDescription),
2526
};
2627

2728
super(nodeVersions, baseDescription);

packages/nodes-base/nodes/Slack/V2/SlackV2.node.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class SlackV2 implements INodeType {
5656
constructor(baseDescription: INodeTypeBaseDescription) {
5757
this.description = {
5858
...baseDescription,
59-
version: [2, 2.1, 2.2, 2.3],
59+
version: [2, 2.1, 2.2, 2.3, 2.4],
6060
defaults: {
6161
name: 'Slack',
6262
},
@@ -574,6 +574,12 @@ export class SlackV2 implements INodeType {
574574
);
575575
responseData = responseData.messages;
576576
}
577+
578+
// Slack API "feature" - messages sorting breaks in-between pages when oldest is provided
579+
// Always sort manually in descending order to ensure consistent sorting
580+
if (nodeVersion >= 2.4) {
581+
responseData.sort((a: IDataObject, b: IDataObject) => +(b.ts ?? 0) - +(a.ts ?? 0));
582+
}
577583
}
578584
//https://api.slack.com/methods/conversations.invite
579585
if (operation === 'invite') {

packages/nodes-base/nodes/Slack/test/v2/Slack.node.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,43 @@ describe('SlackV2', () => {
194194
]);
195195
});
196196

197+
it('should return channel history sorted by timestamp descending for node version >= 2.4', async () => {
198+
mockExecuteFunctions.getNode.mockReturnValue({
199+
...mockNode,
200+
typeVersion: 2.4,
201+
});
202+
203+
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
204+
const params: Record<string, any> = {
205+
resource: 'channel',
206+
operation: 'history',
207+
channelId: 'C123456789',
208+
returnAll: true,
209+
filters: {},
210+
};
211+
return params[paramName];
212+
});
213+
214+
// Mock unsorted messages
215+
const mockResponse = [
216+
{ type: 'message', text: 'Message 2', ts: '1234567892.123456' },
217+
{ type: 'message', text: 'Message 4', ts: '1234567894.123456' },
218+
{ type: 'message', text: 'Message 1', ts: '1234567891.123456' },
219+
{ type: 'message', text: 'Message 3', ts: '1234567893.123456' },
220+
];
221+
slackApiRequestAllItemsSpy.mockResolvedValue(mockResponse);
222+
223+
const result = await node.execute.call(mockExecuteFunctions);
224+
225+
// Verify messages are sorted by timestamp descending (newest first)
226+
expect(result[0][0].json).toEqual([
227+
{ type: 'message', text: 'Message 4', ts: '1234567894.123456' },
228+
{ type: 'message', text: 'Message 3', ts: '1234567893.123456' },
229+
{ type: 'message', text: 'Message 2', ts: '1234567892.123456' },
230+
{ type: 'message', text: 'Message 1', ts: '1234567891.123456' },
231+
]);
232+
});
233+
197234
it('should get all channel history', async () => {
198235
mockExecuteFunctions.getNodeParameter.mockImplementation((paramName: string) => {
199236
const params: Record<string, any> = {

0 commit comments

Comments
 (0)