diff --git a/openvidu-test-integration/package-lock.json b/openvidu-test-integration/package-lock.json index c7a7d9ec..14bbd28c 100644 --- a/openvidu-test-integration/package-lock.json +++ b/openvidu-test-integration/package-lock.json @@ -9,9 +9,9 @@ "version": "1.0.0", "devDependencies": { "@types/jest": "29.5.14", - "@types/node": "22.10.1", + "@types/node": "22.10.2", "jest": "29.7.0", - "mongodb": "6.11.0", + "mongodb": "6.12.0", "ts-jest": "29.2.5", "ts-node": "10.9.2", "typescript": "5.7.2" @@ -47,9 +47,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", "dev": true, "license": "MIT", "engines": { @@ -88,14 +88,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -208,13 +208,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -478,17 +478,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -497,9 +497,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "license": "MIT", "dependencies": { @@ -861,9 +861,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1072,9 +1072,9 @@ } }, "node_modules/@types/node": { - "version": "22.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", - "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", + "version": "22.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", + "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1469,9 +1469,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001686", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001686.tgz", - "integrity": "sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==", + "version": "1.0.30001688", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz", + "integrity": "sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==", "dev": true, "funding": [ { @@ -1651,9 +1651,9 @@ } }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "license": "MIT", "dependencies": { @@ -1740,9 +1740,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.68", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.68.tgz", - "integrity": "sha512-FgMdJlma0OzUYlbrtZ4AeXjKxKPk6KT8WOP8BjcqxWtlg8qyJQjRzPJzUtUn5GBg1oQ26hFs7HOOHJMYiJRnvQ==", + "version": "1.5.73", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz", + "integrity": "sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==", "dev": true, "license": "ISC" }, @@ -2934,9 +2934,9 @@ } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { @@ -3121,14 +3121,14 @@ } }, "node_modules/mongodb": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.11.0.tgz", - "integrity": "sha512-yVbPw0qT268YKhG241vAMLaDQAPbRyTgo++odSgGc9kXnzOujQI60Iyj23B9sQQFPSvmNPvMZ3dsFz0aN55KgA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.12.0.tgz", + "integrity": "sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", - "bson": "^6.10.0", + "bson": "^6.10.1", "mongodb-connection-string-url": "^3.0.0" }, "engines": { @@ -3136,7 +3136,7 @@ }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.1.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", @@ -3200,9 +3200,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, diff --git a/openvidu-test-integration/package.json b/openvidu-test-integration/package.json index f59b513b..e6101f27 100644 --- a/openvidu-test-integration/package.json +++ b/openvidu-test-integration/package.json @@ -2,14 +2,14 @@ "name": "openvidu-test-integration", "version": "1.0.0", "scripts": { - "test": "jest --forceExit", - "test:ci": "jest --ci --json --outputFile=test-results.json --forceExit" + "test": "jest", + "test:ci": "jest --ci --json --outputFile=test-results.json" }, "devDependencies": { "@types/jest": "29.5.14", - "@types/node": "22.10.1", + "@types/node": "22.10.2", "jest": "29.7.0", - "mongodb": "6.11.0", + "mongodb": "6.12.0", "ts-jest": "29.2.5", "ts-node": "10.9.2", "typescript": "5.7.2" diff --git a/openvidu-test-integration/tests/openvidu-active-entities-fixer.test.ts b/openvidu-test-integration/tests/openvidu-active-entities-fixer.test.ts index 9d35a58f..b9f85258 100644 --- a/openvidu-test-integration/tests/openvidu-active-entities-fixer.test.ts +++ b/openvidu-test-integration/tests/openvidu-active-entities-fixer.test.ts @@ -1,12 +1,6 @@ -import { - joinParticipantToRoom, - killProcess, - sleep, - startComposeContainer, - startLocalDeployment, - stopComposeContainer, - stopLocalDeployment -} from "./utils/helper"; +import { killProcess, sleep } from "./utils/helper"; +import { Livekit } from "./utils/livekit"; +import { LocalDeployment } from "./utils/local-deployment"; import { MongoService } from "./utils/mongodb"; import { EntityType } from "./utils/types"; @@ -14,18 +8,22 @@ describe("OpenVidu active entities fixer", () => { const mongoService = MongoService.getInstance(); beforeEach(async () => { - await startLocalDeployment(); + await LocalDeployment.start(); }, 60000); // 1 minute afterEach(() => { - stopLocalDeployment(); + LocalDeployment.stop(); }, 60000); // 1 minute + afterAll(async () => { + await mongoService.disconnect(); + }); + it("should fix fake active entities in MongoDB", async () => { console.log("Joining participant to room..."); const roomName = "TestRoom"; const participantIdentity = "TestParticipant1"; - const pid = joinParticipantToRoom(participantIdentity, roomName); + const pid = Livekit.joinParticipantToRoom(participantIdentity, roomName); await sleep(5); const roomStartedEvent = await mongoService.findStartEvent(EntityType.ROOM, roomName); @@ -41,10 +39,10 @@ describe("OpenVidu active entities fixer", () => { const roomId = roomStartedEvent.room.sid; const participantId = participantActiveEvent.participant_id; - stopComposeContainer("openvidu"); + LocalDeployment.stopContainer("openvidu"); killProcess(pid); await sleep(5); - startComposeContainer("openvidu"); + LocalDeployment.startContainer("openvidu"); // Check if there is a fake close event for room and participant in MongoDB // and the active entities are removed diff --git a/openvidu-test-integration/tests/utils/helper.ts b/openvidu-test-integration/tests/utils/helper.ts index bcd6669b..07cfc6d1 100644 --- a/openvidu-test-integration/tests/utils/helper.ts +++ b/openvidu-test-integration/tests/utils/helper.ts @@ -1,11 +1,6 @@ import { execSync, spawn } from "child_process"; -const LOCAL_DEPLOYMENT_PATH = "../../openvidu-local-deployment/community/docker-compose.yaml"; -const LIVEKIT_URL = "ws://localhost:7880"; -const LIVEKIT_API_KEY = "devkey"; -const LIVEKIT_API_SECRET = "secret"; - -const execCommand = (command: string): string => { +export const execCommand = (command: string): string => { try { return execSync(command).toString().trim(); } catch (error) { @@ -15,14 +10,28 @@ const execCommand = (command: string): string => { } }; -const execCommandInBackground = (command: string, args: string[]): number | undefined => { - const child = spawn(command, args, { detached: true, stdio: "ignore" }); - // child.unref(); +export const execCommandInBackground = (command: string, args: string[]): number | undefined => { + const child = spawn(command, args, { detached: true }); + + child.stdout.on("data", (data) => { + console.log(`stdout (${command}): ${data}`); + }); + child.stderr.on("data", (data) => { + console.log(`stderr (${command}): ${data}`); + }); + child.on("close", (code) => { + console.log(`child process (${command}) exited with code ${code}`); + }); + child.on("error", (error) => { + console.error(`child process (${command}) error: ${error}`); + throw error; + }); + return child.pid; }; export const killProcess = (pid: number) => { - process.kill(-pid); + process.kill(pid); }; export const sleep = async (seconds: number) => { @@ -30,57 +39,3 @@ export const sleep = async (seconds: number) => { setTimeout(resolve, seconds * 1000); }); }; - -export const startLocalDeployment = async () => { - console.log("Starting local deployment..."); - execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} up -d`); - let statusCode: string; - - // Check that container "ready-check" exited with code 0 - do { - await sleep(1); - statusCode = execCommand("docker inspect ready-check -f {{.State.Status}}:{{.State.ExitCode}}"); - } while (statusCode !== "exited:0"); - - console.log("Local deployment started"); -}; - -export const stopLocalDeployment = () => { - console.log("Stopping local deployment..."); - execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} down -v`); -}; - -export const startComposeContainer = (containerName: string) => { - console.log(`Starting container ${containerName}...`); - execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} start ${containerName}`); -}; - -export const stopComposeContainer = (containerName: string) => { - console.log(`Stopping container ${containerName}...`); - execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} stop ${containerName}`); -}; - -export const joinParticipantToRoom = (participantIdentity: string, roomName: string): number => { - const command = "lk"; - const args = [ - "room", - "join", - "--url", - LIVEKIT_URL, - "--api-key", - LIVEKIT_API_KEY, - "--api-secret", - LIVEKIT_API_SECRET, - "--publish-demo", - "--identity", - participantIdentity, - roomName - ]; - const pid = execCommandInBackground(command, args); - - if (!pid) { - throw new Error("Error starting participant"); - } - - return pid; -}; diff --git a/openvidu-test-integration/tests/utils/livekit.ts b/openvidu-test-integration/tests/utils/livekit.ts new file mode 100644 index 00000000..1e8539e1 --- /dev/null +++ b/openvidu-test-integration/tests/utils/livekit.ts @@ -0,0 +1,31 @@ +import { execCommandInBackground } from "./helper"; + +const LIVEKIT_URL = "ws://localhost:7880"; +const LIVEKIT_API_KEY = "devkey"; +const LIVEKIT_API_SECRET = "secret"; + +const LK_CLI = "lk"; + +export class Livekit { + static joinParticipantToRoom(participantIdentity: string, roomName: string): number { + const args = [ + "room", + "join", + "--url", + LIVEKIT_URL, + "--api-key", + LIVEKIT_API_KEY, + "--api-secret", + LIVEKIT_API_SECRET, + "--publish-demo", + "--identity", + participantIdentity, + roomName + ]; + const pid = execCommandInBackground(LK_CLI, args); + if (!pid) { + throw new Error("Error joining participant to room"); + } + return pid; + } +} diff --git a/openvidu-test-integration/tests/utils/local-deployment.ts b/openvidu-test-integration/tests/utils/local-deployment.ts new file mode 100644 index 00000000..16166967 --- /dev/null +++ b/openvidu-test-integration/tests/utils/local-deployment.ts @@ -0,0 +1,34 @@ +import { execCommand, sleep } from "./helper"; + +const LOCAL_DEPLOYMENT_PATH = "../../openvidu-local-deployment/community/docker-compose.yaml"; + +export class LocalDeployment { + static async start() { + console.log("Starting local deployment..."); + execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} up -d`); + let statusCode: string; + + // Check that container "ready-check" exited with code 0 + do { + await sleep(1); + statusCode = execCommand("docker inspect ready-check -f {{.State.Status}}:{{.State.ExitCode}}"); + } while (statusCode !== "exited:0"); + + console.log("Local deployment started"); + } + + static stop() { + console.log("Stopping local deployment..."); + execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} down -v`); + } + + static startContainer(containerName: string) { + console.log(`Starting container ${containerName}...`); + execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} start ${containerName}`); + } + + static stopContainer(containerName: string) { + console.log(`Stopping container ${containerName}...`); + execCommand(`docker compose -f ${LOCAL_DEPLOYMENT_PATH} stop ${containerName}`); + } +} diff --git a/openvidu-test-integration/tests/utils/mongodb.ts b/openvidu-test-integration/tests/utils/mongodb.ts index 93314722..e07b5353 100644 --- a/openvidu-test-integration/tests/utils/mongodb.ts +++ b/openvidu-test-integration/tests/utils/mongodb.ts @@ -46,6 +46,24 @@ export class MongoService { return MongoService.instace; } + public async connect(): Promise { + try { + await this.client.connect(); + } catch (error) { + console.error("Error connecting to MongoDB", error); + throw error; + } + } + + public async disconnect(): Promise { + try { + await this.client.close(); + } catch (error) { + console.error("Error disconnecting from MongoDB", error); + throw error; + } + } + public async findStartEvent(entityType: EntityType, entityName: string): Promise | null> { try { const eventType = entityStartEventTypesMap.get(entityType)!;