Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f3d88c8
test: initial draft of integration tests for federation
Oct 10, 2025
3c54a58
test: move tests to federation-matrix and finish all three tests
Oct 13, 2025
8bd09d1
test: undo changes in yarn.lock
Oct 20, 2025
b1d9578
test: undoing unecessary changes
Oct 15, 2025
6448895
test: Add element flag to test live with element
Oct 19, 2025
1ea5bb5
test: docker compose and integration test script running both local a…
Oct 20, 2025
9f23c9e
test: remove script directory from package root
Oct 20, 2025
05768ad
test: --image without args runs on latest rc image
Oct 21, 2025
3f84a29
test: undo yarn.lock changes
Oct 21, 2025
3838ea2
test: apply necessary changes to yarn.lock
Oct 21, 2025
6f36df7
test: remove unecessary traefix config
Oct 22, 2025
26b81bd
test: fixing automated code reviews
Oct 22, 2025
3270282
test: ignore integration tests in unit tests for federation-matrix
Oct 22, 2025
228b2e3
test: fix linting issues
Oct 22, 2025
837cb8f
test: fix review related to tls for synapse
Oct 22, 2025
e73ba17
test: add readme explaining how integration tests work and fix minor …
Oct 22, 2025
fc75ee1
test: renaming types and prettify
Oct 23, 2025
eaa3243
test: first draft of the pipeline job for federation testing
Oct 23, 2025
fd302f5
test: replace docker-compose with docker compose
Oct 23, 2025
09fa97c
test: debug commit
Oct 23, 2025
a96088d
test: more ci changes for debugging
Oct 23, 2025
40fff32
test: add certificates for rc1, hs1, and element along with .gitignor…
Oct 23, 2025
be67235
test: more debugging changes to the pipeline
Oct 23, 2025
17e4cdf
test: add some logging
Oct 23, 2025
c84cf28
test: change enterprise license and debug logging for federation test…
Oct 25, 2025
403ca57
test: bring back all pipeline jobs
dhulke Oct 25, 2025
ca997fa
test: remove storybook from tests
dhulke Oct 25, 2025
51e39ab
test: enhance documentation for federation testing utilities and conf…
dhulke Oct 26, 2025
310479f
test: fix integration tests
dhulke Oct 26, 2025
93471f7
test: add second set of tests. Inviting users to non-federated privat…
dhulke Oct 26, 2025
e3cbdfb
test: getting rid of unecessary local variables and add room id valid…
dhulke Oct 26, 2025
9a035a9
fix: federated in non federated room check (api)
dhulke Oct 26, 2025
0b4be1f
fix: invite federated user to non federated room
dhulke Oct 26, 2025
58b18b2
fix: slash command error message
dhulke Oct 27, 2025
d266105
test: add test cases and fix room creation logic to return error when…
dhulke Oct 27, 2025
2171077
test: starting last set of room tests
dhulke Oct 28, 2025
b61e236
test: All room tests finished
dhulke Oct 28, 2025
efa7d47
test: starting message testing
dhulke Nov 9, 2025
7676c44
Merge branch 'develop' into test/federation-integration
dhulke Nov 9, 2025
b95a811
test: fix yarn.lock
dhulke Nov 9, 2025
41188bb
test: fix pipeline
dhulke Nov 9, 2025
9915693
test: adding an exception for tests/data in .gitignore
dhulke Nov 10, 2025
3853c0f
Merge branch 'develop' into test/federation-integration
dhulke Nov 14, 2025
4ff80ac
fix: yarn.lock
dhulke Nov 14, 2025
79abaef
test: update action version
dhulke Nov 14, 2025
5865fdc
fix: download-artifact@v6
dhulke Nov 14, 2025
66b8907
fix: skip cache if not present
dhulke Nov 15, 2025
e6d5115
Merge branch 'develop' into test/federation-integration
dhulke Nov 15, 2025
929c0e1
fix: review
dhulke Nov 15, 2025
9e97b36
test: message media tests
dhulke Nov 15, 2025
7ed701b
Merge branch 'develop' into test/federation-media-messages
dhulke Nov 17, 2025
109705a
Merge branch 'develop' into test/federation-media-messages
dhulke Nov 25, 2025
975fd4f
chore: qase integration (#37538)
dhulke Nov 25, 2025
377df86
Update ee/packages/federation-matrix/tests/setup-qase.ts
dhulke Nov 29, 2025
94f1f20
Merge branch 'develop' into test/federation-media-messages
dhulke Nov 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ jobs:
env:
ROCKETCHAT_IMAGE: ghcr.io/${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat:${{ needs.release-versions.outputs.gh-docker-tag }}
ENTERPRISE_LICENSE_RC1: ${{ secrets.ENTERPRISE_LICENSE_RC1 }}
QASE_TESTOPS_JEST_API_TOKEN: ${{ secrets.QASE_TESTOPS_JEST_API_TOKEN }}
run: yarn test:integration --image "${ROCKETCHAT_IMAGE}"

report-coverage:
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/lib/server/functions/createRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ async function createUsersSubscriptions({
await Rooms.incUsersCountById(room._id, subs.length);
}

// eslint-disable-next-line complexity
export const createRoom = async <T extends RoomType>(
type: T,
name: T extends 'd' ? undefined : string,
Expand Down
170 changes: 170 additions & 0 deletions apps/meteor/tests/data/file.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import * as fs from 'fs';

import type { IMessage } from '@rocket.chat/core-typings';

import { api } from './api-data';
import type { IRequestConfig } from './users.helper';

/**
* Uploads a file to Rocket.Chat using the two-step process (rooms.media then rooms.mediaConfirm).
*
* @param roomId - The room ID where the file will be uploaded
* @param filePath - Path to the file to upload
* @param description - Description for the file
* @param config - Request configuration with credentials and request instance
* @param message - Optional message text to include with the file
* @returns Promise resolving to the message response
*/
export async function uploadFileToRC(
roomId: string,
filePath: string,
description: string,
config: IRequestConfig,
message = '',
): Promise<{ message: IMessage }> {
const requestInstance = config.request;
const credentialsInstance = config.credentials;

// Step 1: Upload file to rooms.media/:rid
const mediaResponse = await requestInstance
.post(api(`rooms.media/${roomId}`))
.set(credentialsInstance)
.attach('file', filePath)
.expect('Content-Type', 'application/json')
.expect(200);

if (!mediaResponse.body.success || !mediaResponse.body.file?._id) {
throw new Error(`File upload failed: ${JSON.stringify(mediaResponse.body)}`);
}

const fileId = mediaResponse.body.file._id;

// Step 2: Confirm and send message with rooms.mediaConfirm/:rid/:fileId
const confirmResponse = await requestInstance
.post(api(`rooms.mediaConfirm/${roomId}/${fileId}`))
.set(credentialsInstance)
.send({
msg: message,
description,
})
.expect('Content-Type', 'application/json')
.expect(200);

if (!confirmResponse.body.success || !confirmResponse.body.message) {
throw new Error(`File confirmation failed: ${JSON.stringify(confirmResponse.body)}`);
}

return confirmResponse.body;
}

/**
* Gets the list of files for a room.
*
* @param roomId - The room ID
* @param config - Request configuration
* @param options - Optional query parameters (name for filtering, count, offset)
* @returns Promise resolving to the files list response
*/
export async function getFilesList(
roomId: string,
config: IRequestConfig,
options: { name?: string; count?: number; offset?: number } = {},
): Promise<{
files: Array<{
_id: string;
name: string;
size: number;
type: string;
rid: string;
userId: string;
path?: string;
url?: string;
uploadedAt?: string;
federation?: {
mrid?: string;
mxcUri?: string;
serverName?: string;
mediaId?: string;
};
}>;
count: number;
offset: number;
total: number;
success: boolean;
}> {
const requestInstance = config.request;
const credentialsInstance = config.credentials;

const queryParams: Record<string, string> = {
roomId,
count: String(options.count || 10),
offset: String(options.offset || 0),
sort: JSON.stringify({ uploadedAt: -1 }),
};

if (options.name) {
queryParams.name = options.name;
}

const response = await requestInstance
.get(api('groups.files'))
.set(credentialsInstance)
.query(queryParams)
.expect('Content-Type', 'application/json')
.expect(200);

if (!response.body.success) {
throw new Error(`Failed to get files list: ${JSON.stringify(response.body)}`);
}

return response.body;
}

/**
* Downloads a file and verifies it matches the original file using binary comparison.
*
* @param fileUrl - The URL to download the file from (relative path like /file-upload/...)
* @param originalFilePath - Path to the original file to compare against
* @param config - Request configuration
* @returns Promise resolving to true if files match byte-by-byte
*/
export async function downloadFileAndVerifyBinary(fileUrl: string, originalFilePath: string, config: IRequestConfig): Promise<boolean> {
const requestInstance = config.request;
const credentialsInstance = config.credentials;

const response = await requestInstance.get(fileUrl).set(credentialsInstance).expect(200);

// Handle different response types:
// - For text/plain, supertest parses as JSON (resulting in {}), so use response.text
// - For binary files, response.body might be a Buffer
// - For other text types, response.text contains the content
let downloadedBuffer: Buffer;
if (Buffer.isBuffer(response.body)) {
// Binary file - response.body is already a Buffer
downloadedBuffer = response.body;
} else if (response.text !== undefined) {
// Text response (including text/plain) - use response.text to avoid JSON parsing
// Convert to Buffer using binary encoding to preserve exact bytes
downloadedBuffer = Buffer.from(response.text, 'binary');
} else if (typeof response.body === 'string') {
// Fallback: if body is a string, convert to buffer
downloadedBuffer = Buffer.from(response.body, 'binary');
} else {
// If body is an object (like {} from JSON parsing), this is an error
throw new Error(
`Failed to get file content. Response body type: ${typeof response.body}. ` +
`This usually means supertest parsed a text/plain response as JSON. ` +
`Response text available: ${response.text !== undefined ? 'yes' : 'no'}`,
);
}

// Read the original file
const originalBuffer = fs.readFileSync(originalFilePath);

// Compare buffers byte-by-byte
if (downloadedBuffer.length !== originalBuffer.length) {
return false;
}

return downloadedBuffer.equals(originalBuffer);
}
21 changes: 21 additions & 0 deletions ee/packages/federation-matrix/jest.config.federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ export default {
forceExit: true, // Force Jest to exit after tests complete
detectOpenHandles: true, // Detect open handles that prevent Jest from exiting
globalTeardown: '<rootDir>/tests/teardown.ts',
// To disable Qase integration, remove this line or comment it out
setupFilesAfterEnv: ['<rootDir>/tests/setup-qase.ts'],
verbose: false,
silent: false,
reporters: [
'default',
...(process.env.QASE_TESTOPS_JEST_API_TOKEN
? [
[
'jest-qase-reporter',
{
mode: 'testops',
testops: {
api: { token: process.env.QASE_TESTOPS_JEST_API_TOKEN },
project: 'RC',
run: { complete: true },
},
debug: true,
},
] as [string, { [x: string]: unknown }],
]
: []),
] as Config['reporters'],
} satisfies Config;
Loading
Loading