snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
170
apps/meteor/tests/data/file.helper.ts
Normal file
170
apps/meteor/tests/data/file.helper.ts
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user