Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -656,6 +656,7 @@ jobs:
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 }}
PR_NUMBER: ${{ github.event.number }}
run: yarn test:integration --image "${ROCKETCHAT_IMAGE}"

report-coverage:
Expand Down
21 changes: 20 additions & 1 deletion ee/packages/federation-matrix/jest.config.federation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
import server from '@rocket.chat/jest-presets/server';
import type { Config } from 'jest';

function qaseRunTitle(): string {
const title = ['Federation E2E Tests'];

if (process.env.PR_NUMBER) {
title.push(`PR ${process.env.PR_NUMBER}`);
}

if (process.env.GITHUB_RUN_ID) {
title.push(`Run ${process.env.GITHUB_RUN_ID}`);
}

title.push(new Date().toISOString());

return title.join(' - ');
}

export default {
preset: server.preset,
transformIgnorePatterns: [
Expand Down Expand Up @@ -36,7 +52,10 @@ export default {
testops: {
api: { token: process.env.QASE_TESTOPS_JEST_API_TOKEN },
project: 'RC',
run: { complete: true },
run: {
title: qaseRunTitle(),
complete: true,
},
},
debug: true,
},
Expand Down
2 changes: 1 addition & 1 deletion ee/packages/federation-matrix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"lint:fix": "eslint src --fix",
"test": "jest",
"test:integration": "./tests/scripts/run-integration-tests.sh",
"testend-to-end": "IS_EE=true NODE_EXTRA_CA_CERTS=$(pwd)/docker-compose/traefik/certs/ca/rootCA.crt jest --config jest.config.federation.ts --forceExit --testTimeout=30000",
"test:federation": "jest --config jest.config.federation.ts",
"testunit": "jest",
"typecheck": "tsc --noEmit --skipLibCheck"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { SynapseClient } from '../helper/synapse-client';
beforeAll(async () => {
// Create admin request config for RC1
rc1AdminRequestConfig = await getRequestConfig(
federationConfig.rc1.apiUrl,
federationConfig.rc1.url,
federationConfig.rc1.adminUser,
federationConfig.rc1.adminPassword,
);
Expand Down
8 changes: 4 additions & 4 deletions ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { SynapseClient } from '../helper/synapse-client';
beforeAll(async () => {
// Create admin request config for RC1
rc1AdminRequestConfig = await getRequestConfig(
federationConfig.rc1.apiUrl,
federationConfig.rc1.url,
federationConfig.rc1.adminUser,
federationConfig.rc1.adminPassword,
);
Expand All @@ -48,7 +48,7 @@ import { SynapseClient } from '../helper/synapse-client';

// Create user1 request config for RC1
rc1User1RequestConfig = await getRequestConfig(
federationConfig.rc1.apiUrl,
federationConfig.rc1.url,
federationConfig.rc1.additionalUser1.username,
federationConfig.rc1.additionalUser1.password,
);
Expand Down Expand Up @@ -84,7 +84,7 @@ import { SynapseClient } from '../helper/synapse-client';
beforeAll(async () => {
const user = { username: `user-${Date.now()}`, password: '123' };
createdUser = await createUser(user, rc1AdminRequestConfig);
userRequestConfig = await getRequestConfig(federationConfig.rc1.apiUrl, user.username, user.password);
userRequestConfig = await getRequestConfig(federationConfig.rc1.url, user.username, user.password);
});

afterAll(async () => {
Expand Down Expand Up @@ -256,7 +256,7 @@ import { SynapseClient } from '../helper/synapse-client';
describe('Go to the composer and use the /invite slash command to add a federated user', () => {
it('It should not allow and show an error message', async () => {
// Set up DDP listener to catch ephemeral messages
const ddpListener = createDDPListener(federationConfig.rc1.apiUrl, rc1AdminRequestConfig);
const ddpListener = createDDPListener(federationConfig.rc1.url, rc1AdminRequestConfig);

// Connect to DDP and subscribe to ephemeral messages
await ddpListener.connect();
Expand Down
102 changes: 44 additions & 58 deletions ee/packages/federation-matrix/tests/helper/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,22 @@
* Rocket.Chat instances, Matrix homeservers, and user credentials needed
* for end-to-end federation testing.
*/
export interface IFederationConfig {
rc1: {
apiUrl: string;
adminUser: string;
adminPassword: string;
adminMatrixUserId: string;
additionalUser1: {
username: string;
password: string;
matrixUserId: string;
};
};
hs1: {
url: string;
adminMatrixUserId: string;

type FederationServerConfig = {
url: string;
domain: string;
adminUser: string;
adminPassword: string;
adminMatrixUserId: string;
additionalUser1: {
username: string;
password: string;
homeserver: string;
adminUser: string;
adminPassword: string;
additionalUser1: {
username: string;
password: string;
matrixUserId: string;
};
matrixUserId: string;
};
};
export interface IFederationConfig {
rc1: FederationServerConfig;
hs1: FederationServerConfig;
}

/**
Expand All @@ -40,13 +31,12 @@ export interface IFederationConfig {
* Throws an error if a required variable is missing or empty.
*
* @param name - The name of the environment variable for error messages
* @param value - The environment variable value (may be undefined)
* @param defaultValue - Optional default value to use if variable is not set
* @returns The validated value (either the env var or default)
* @throws Error if the variable is required but missing or empty
*/
function validateEnvVar(name: string, value: string | undefined, defaultValue?: string): string {
const finalValue = value || defaultValue;
function validateEnvVar(name: string, defaultValue?: string): string {
const finalValue = process.env[name] || defaultValue;
if (!finalValue || finalValue.trim() === '') {
throw new Error(`Required environment variable ${name} is not set or is empty`);
}
Expand All @@ -65,45 +55,41 @@ function validateEnvVar(name: string, value: string | undefined, defaultValue?:
* @throws Error if any required configuration is missing or invalid
*/
function getFederationConfig(): IFederationConfig {
const rcDomain = validateEnvVar('FEDERATION_RC1_DOMAIN', 'rc1');
const rcAdminUser = validateEnvVar('FEDERATION_RC1_ADMIN_USER', 'admin');
const rcAdminPassword = validateEnvVar('FEDERATION_RC1_ADMIN_PASSWORD', 'admin');
const rcAdditionalUser1 = validateEnvVar('FEDERATION_RC1_ADDITIONAL_USER1', 'user2');
const rcAdditionalUser1Password = validateEnvVar('FEDERATION_RC1_ADDITIONAL_USER1_PASSWORD', 'user2pass');

const hs1Domain = validateEnvVar('FEDERATION_SYNAPSE_DOMAIN', 'hs1');
const hs1AdminUser = validateEnvVar('FEDERATION_SYNAPSE_ADMIN_USER', 'admin');
const hs1AdminPassword = validateEnvVar('FEDERATION_SYNAPSE_ADMIN_PASSWORD', 'admin');
const hs1AdditionalUser1 = validateEnvVar('FEDERATION_SYNAPSE_ADDITIONAL_USER1', 'alice');
const hs1AdditionalUser1Password = validateEnvVar('FEDERATION_SYNAPSE_ADDITIONAL_USER1_PASSWORD', 'alice');

return {
rc1: {
apiUrl: validateEnvVar('FEDERATION_RC1_API_URL', process.env.FEDERATION_RC1_API_URL, 'https://rc1'),
adminUser: validateEnvVar('FEDERATION_RC1_ADMIN_USER', process.env.FEDERATION_RC1_ADMIN_USER, 'admin'),
adminPassword: validateEnvVar('FEDERATION_RC1_ADMIN_PASSWORD', process.env.FEDERATION_RC1_ADMIN_PASSWORD, 'admin'),
adminMatrixUserId: validateEnvVar('FEDERATION_RC1_USER_ID', process.env.FEDERATION_RC1_USER_ID, '@admin:rc1'),
url: `https://${rcDomain}`,
domain: rcDomain,
adminUser: rcAdminUser,
adminPassword: rcAdminPassword,
adminMatrixUserId: `@${rcAdminUser}:${rcDomain}`,
additionalUser1: {
username: validateEnvVar('FEDERATION_RC1_ADDITIONAL_USER1', process.env.FEDERATION_RC1_ADDITIONAL_USER1, 'user2'),
password: validateEnvVar(
'FEDERATION_RC1_ADDITIONAL_USER1_PASSWORD',
process.env.FEDERATION_RC1_ADDITIONAL_USER1_PASSWORD,
'user2pass',
),
matrixUserId: validateEnvVar(
'FEDERATION_RC1_ADDITIONAL_USER1_MATRIX_ID',
process.env.FEDERATION_RC1_ADDITIONAL_USER1_MATRIX_ID,
'@user2:rc1',
),
username: rcAdditionalUser1,
password: rcAdditionalUser1Password,
matrixUserId: `@${rcAdditionalUser1}:${rcDomain}`,
},
},
hs1: {
url: validateEnvVar('FEDERATION_SYNAPSE_URL', process.env.FEDERATION_SYNAPSE_URL, 'https://hs1'),
adminMatrixUserId: validateEnvVar('FEDERATION_SYNAPSE_USER', process.env.FEDERATION_SYNAPSE_USER, '@admin:hs1'),
password: validateEnvVar('FEDERATION_SYNAPSE_PASSWORD', process.env.FEDERATION_SYNAPSE_PASSWORD, 'admin'),
homeserver: validateEnvVar('FEDERATION_SYNAPSE_HOMESERVER', process.env.FEDERATION_SYNAPSE_HOMESERVER, 'hs1'),
adminUser: validateEnvVar('FEDERATION_SYNAPSE_ADMIN_USER', process.env.FEDERATION_SYNAPSE_ADMIN_USER, 'admin'),
adminPassword: validateEnvVar('FEDERATION_SYNAPSE_ADMIN_PASSWORD', process.env.FEDERATION_SYNAPSE_ADMIN_PASSWORD, 'admin'),
url: `https://${hs1Domain}`,
domain: hs1Domain,
adminUser: hs1AdminUser,
adminMatrixUserId: `@${hs1AdminUser}:${hs1Domain}`,
adminPassword: hs1AdminPassword,
additionalUser1: {
username: validateEnvVar('FEDERATION_SYNAPSE_ADDITIONAL_USER1', process.env.FEDERATION_SYNAPSE_ADDITIONAL_USER1, 'alice'),
password: validateEnvVar(
'FEDERATION_SYNAPSE_ADDITIONAL_USER1_PASSWORD',
process.env.FEDERATION_SYNAPSE_ADDITIONAL_USER1_PASSWORD,
'alice',
),
matrixUserId: validateEnvVar(
'FEDERATION_SYNAPSE_ADDITIONAL_USER1_MATRIX_ID',
process.env.FEDERATION_SYNAPSE_ADDITIONAL_USER1_MATRIX_ID,
'@alice:hs1',
),
username: hs1AdditionalUser1,
password: hs1AdditionalUser1Password,
matrixUserId: `@${hs1AdditionalUser1}:${hs1Domain}`,
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ cleanup() {
echo "=========================================="
echo "CONTAINER LOGS (Test Failed)"
echo "=========================================="

echo ""
echo "ROCKET.CHAT (rc1) LOGS:"
echo "----------------------------------------"
Expand All @@ -119,7 +119,7 @@ cleanup() {
else
echo " Rocket.Chat container not found or no logs"
fi

echo ""
echo "SYNAPSE (hs1) LOGS:"
echo "----------------------------------------"
Expand All @@ -128,11 +128,11 @@ cleanup() {
else
echo " Synapse container not found or no logs"
fi

echo ""
echo "=========================================="
fi

if [ "$KEEP_RUNNING" = true ]; then
log_info "Keeping Docker containers running (--keep-running flag set)"
log_info "Services are available at:"
Expand All @@ -158,12 +158,12 @@ cleanup() {
fi
log_success "Cleanup completed"
fi

# Remove temporary build directory if it exists
if [ -n "${BUILD_DIR:-}" ] && [ -d "$BUILD_DIR" ]; then
rm -rf "$BUILD_DIR" || true
fi

# Exit with the test result code
if [ -n "${TEST_EXIT_CODE:-}" ]; then
exit $TEST_EXIT_CODE
Expand All @@ -186,21 +186,21 @@ fi
if [ "$USE_PREBUILT_IMAGE" = false ]; then
log_info "🚀 Building Rocket.Chat locally..."
log_info "====================================="

# Clean up any existing build
log_info "Cleaning up previous build..."
rm -rf "$BUILD_DIR"

# Build the project
log_info "Building packages from project root..."
cd "$ROCKETCHAT_ROOT"
yarn build

# Build the Meteor bundle (must be run from the meteor directory)
log_info "Building Meteor bundle..."
cd "$ROCKETCHAT_ROOT/apps/meteor"
METEOR_DISABLE_OPTIMISTIC_CACHING=1 meteor build --server-only --directory "$BUILD_DIR"

log_success "Build completed!"
else
log_info "🚀 Using pre-built image: $PREBUILT_IMAGE"
Expand Down Expand Up @@ -289,7 +289,7 @@ wait_for_service() {
# Capture curl output and error for debugging
curl_output=$(curl -fsS --cacert "$ca_cert" --resolve "${host}:${port}:127.0.0.1" "$url" 2>&1)
curl_exit_code=$?

if [ $curl_exit_code -eq 0 ]; then
log_success "$name is ready!"
return 0
Expand Down Expand Up @@ -328,8 +328,8 @@ fi
if [ "$NO_TEST" = false ]; then
log_info "Running end-to-end tests..."
cd "$PACKAGE_ROOT"
yarn testend-to-end

IS_EE=true NODE_EXTRA_CA_CERTS=$(pwd)/docker-compose/traefik/certs/ca/rootCA.crt yarn test:federation
TEST_EXIT_CODE=$?
else
log_info "No-test mode: skipping test execution"
Expand Down
Loading
Loading