Skip to content

Commit 7204642

Browse files
ggazzosampaiodiego
authored andcommitted
test: refactor end-to-end test for inviting a user from Synapse to ensure proper member and message reflection
1 parent cb69a57 commit 7204642

File tree

3 files changed

+103
-6
lines changed

3 files changed

+103
-6
lines changed

apps/meteor/tests/data/rooms.helper.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,30 @@ export const acceptRoomInvite = (roomId: IRoom['_id'], config?: IRequestConfig)
454454
});
455455
};
456456

457+
/**
458+
* Retrieves the subscriptions for the authenticated user.
459+
*
460+
* Fetches the complete list of subscriptions for the authenticated user, which is essential
461+
* for verifying federation subscription synchronization and member synchronization.
462+
*
463+
* @param config - Optional request configuration for custom domains
464+
* @returns Promise resolving to the subscriptions response
465+
*/
466+
467+
export const getSubscriptions = (config?: IRequestConfig) => {
468+
const requestInstance = config?.request || request;
469+
const credentialsInstance = config?.credentials || credentials;
470+
471+
return new Promise<ReturnType<Endpoints['/v1/subscriptions.get']['GET']>>((resolve) => {
472+
void requestInstance
473+
.get(api('subscriptions.get'))
474+
.set(credentialsInstance)
475+
.end((_err: any, req: any) => {
476+
resolve(req.body);
477+
});
478+
});
479+
};
480+
457481
/**
458482
* Rejects a room invite for the authenticated user.
459483
*

ee/packages/federation-matrix/tests/end-to-end/room.spec.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
addUserToRoomSlashCommand,
1010
acceptRoomInvite,
1111
rejectRoomInvite,
12+
getRoomMembers,
13+
getSubscriptions,
1214
} from '../../../../../apps/meteor/tests/data/rooms.helper';
1315
import { type IRequestConfig, getRequestConfig, createUser, deleteUser } from '../../../../../apps/meteor/tests/data/users.helper';
1416
import { IS_EE } from '../../../../../apps/meteor/tests/e2e/config/constants';
@@ -1563,14 +1565,58 @@ import { SynapseClient } from '../helper/synapse-client';
15631565
// RC view: Admin tries to accept rc1User1's invitation
15641566
const response = await acceptRoomInvite(federatedChannel._id, rc1AdminRequestConfig);
15651567
expect(response.success).toBe(false);
1566-
expect(response.error).toBe('Failed to handle invite: No subscription found or user does not have permission to accept or reject this invite');
1568+
expect(response.error).toBe(
1569+
'Failed to handle invite: No subscription found or user does not have permission to accept or reject this invite',
1570+
);
15671571
});
15681572

15691573
it('It should not allow admin to reject invitation on behalf of another user', async () => {
15701574
// RC view: Admin tries to reject rc1User1's invitation
15711575
const response = await rejectRoomInvite(federatedChannel._id, rc1AdminRequestConfig);
15721576
expect(response.success).toBe(false);
1573-
expect(response.error).toBe('Failed to handle invite: No subscription found or user does not have permission to accept or reject this invite');
1577+
expect(response.error).toBe(
1578+
'Failed to handle invite: No subscription found or user does not have permission to accept or reject this invite',
1579+
);
1580+
});
1581+
});
1582+
});
1583+
1584+
describe('Inviting a RC user from Synapse', () => {
1585+
describe('Room that already contains previous events', () => {
1586+
let matrixRoomId: string;
1587+
let channelName: string;
1588+
let rid: string;
1589+
beforeAll(async () => {
1590+
channelName = `federated-channel-from-synapse-${Date.now()}`;
1591+
matrixRoomId = await hs1AdminApp.createRoom(channelName);
1592+
1593+
await hs1AdminApp.matrixClient.sendTextMessage(matrixRoomId, 'Message from admin');
1594+
await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.hs1.additionalUser1.matrixUserId);
1595+
await hs1User1App.matrixClient.joinRoom(matrixRoomId);
1596+
await hs1User1App.matrixClient.sendTextMessage(matrixRoomId, 'Message from user1');
1597+
await hs1AdminApp.matrixClient.invite(matrixRoomId, federationConfig.rc1.adminMatrixUserId);
1598+
1599+
const subscriptions = await getSubscriptions(rc1AdminRequestConfig);
1600+
1601+
const pendingInvitation = subscriptions.update.find((subscription) => subscription.status === 'INVITED');
1602+
1603+
expect(pendingInvitation).not.toBeUndefined();
1604+
1605+
rid = pendingInvitation?.rid!;
1606+
1607+
await acceptRoomInvite(rid, rc1AdminRequestConfig);
1608+
}, 15000);
1609+
1610+
describe('It should reflect all the members and messagens on the rocket.chat side', () => {
1611+
it('It should show all the three users in the members list', async () => {
1612+
const members = await getRoomMembers(rid, rc1AdminRequestConfig);
1613+
expect(members.members.length).toBe(3);
1614+
expect(members.members.find((member: IUser) => member.username === federationConfig.rc1.adminUser)).not.toBeNull();
1615+
expect(
1616+
members.members.find((member: IUser) => member.username === federationConfig.rc1.additionalUser1.username),
1617+
).not.toBeNull();
1618+
expect(members.members.find((member: IUser) => member.username === federationConfig.hs1.adminMatrixUserId)).not.toBeNull();
1619+
});
15741620
});
15751621
});
15761622
});

ee/packages/federation-matrix/tests/helper/synapse-client.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import * as fs from 'fs';
88
import * as path from 'path';
99

10-
import { createClient, type MatrixClient, KnownMembership, type Room, type RoomMember } from 'matrix-js-sdk';
10+
import { createClient, type MatrixClient, KnownMembership, type Room, type RoomMember, Visibility } from 'matrix-js-sdk';
1111

1212
/**
1313
* Creates a promise that resolves after the specified delay.
@@ -30,7 +30,7 @@ export function wait(ms: number): Promise<void> {
3030
* invitation handling with built-in retry logic for eventual consistency.
3131
*/
3232
export class SynapseClient {
33-
private matrixClient: MatrixClient | null = null;
33+
private _matrixClient: MatrixClient | null = null;
3434

3535
private url: string;
3636

@@ -51,6 +51,13 @@ export class SynapseClient {
5151
this.password = password;
5252
}
5353

54+
get matrixClient(): MatrixClient {
55+
if (!this._matrixClient) {
56+
throw new Error('Matrix client is not initialized');
57+
}
58+
return this._matrixClient;
59+
}
60+
5461
/**
5562
* Initializes the Matrix client connection.
5663
*
@@ -63,7 +70,7 @@ export class SynapseClient {
6370
async initialize(): Promise<void> {
6471
const client = await this.createClient(this.username, this.password, this.url);
6572
await client.startClient();
66-
this.matrixClient = client;
73+
this._matrixClient = client;
6774
}
6875

6976
/**
@@ -132,6 +139,26 @@ export class SynapseClient {
132139
throw new Error(`No room found with name ${roomName}`);
133140
}
134141

142+
async createRoom(roomName: string, visibility: Visibility = Visibility.Private): Promise<string> {
143+
if (!this.matrixClient) {
144+
throw new Error('Matrix client is not initialized');
145+
}
146+
147+
const room = await this.matrixClient.createRoom({
148+
name: roomName,
149+
visibility,
150+
});
151+
152+
return room.room_id;
153+
}
154+
155+
async inviteUserToRoom(roomId: string, userId: string): Promise<void> {
156+
if (!this.matrixClient) {
157+
throw new Error('Matrix client is not initialized');
158+
}
159+
await this.matrixClient.invite(userId, roomId);
160+
}
161+
135162
/**
136163
* Finds a room by name and membership status.
137164
*
@@ -664,7 +691,7 @@ export class SynapseClient {
664691
await this.matrixClient.clearStores?.();
665692
this.matrixClient.removeAllListeners();
666693
await this.matrixClient.logout(true);
667-
this.matrixClient = null;
694+
this._matrixClient = null;
668695
}
669696
}
670697
}

0 commit comments

Comments
 (0)