2021-06-06 22:01:37 +08:00
|
|
|
const Page = require('../core/page');
|
|
|
|
const { exec } = require("child_process");
|
2021-11-06 04:16:42 +08:00
|
|
|
const { CLIENT_RECONNECTION_TIMEOUT, ELEMENT_WAIT_TIME } = require('../core/constants'); // core constants (Timeouts vars imported)
|
2021-06-06 22:01:37 +08:00
|
|
|
const { sleep } = require('../core/helper');
|
2021-11-06 04:16:42 +08:00
|
|
|
const screenshareUtil = require('../screenshare/util');
|
2021-08-21 04:33:57 +08:00
|
|
|
const e = require('../core/elements');
|
2021-11-06 04:16:42 +08:00
|
|
|
const { checkElement } = require('../core/util');
|
2021-06-06 22:01:37 +08:00
|
|
|
|
|
|
|
class Trigger extends Page {
|
|
|
|
constructor() {
|
2021-09-23 03:22:47 +08:00
|
|
|
super();
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
async triggerMeteorDisconnect(testName) {
|
2021-08-14 01:35:00 +08:00
|
|
|
try {
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `01-after-audio-modal-close-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-08-14 01:35:00 +08:00
|
|
|
await sleep(5000);
|
|
|
|
await this.page.evaluate(() => Meteor.disconnect());
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `02-after-meteor-disconnection-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-08-14 01:35:00 +08:00
|
|
|
await sleep(CLIENT_RECONNECTION_TIMEOUT);
|
|
|
|
const meteorStatus = await this.page.evaluate(() => Meteor.status());
|
|
|
|
const meteorStatusConfirm = await meteorStatus.status === "offline";
|
|
|
|
await this.logger('Check if Meteor is Offline => ', meteorStatusConfirm);
|
2021-09-22 11:51:29 +08:00
|
|
|
const getAudioButton = await this.page.evaluate((joinAudioSelector) => {
|
|
|
|
return document.querySelectorAll(joinAudioSelector)[0].getAttribute('aria-disabled') === "true";
|
|
|
|
}, e.joinAudio);
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.logger('Check if Connections Buttons are disabled => ', getAudioButton);
|
|
|
|
await this.page.evaluate(() => Meteor.reconnect());
|
|
|
|
await sleep(3000);
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `03-after-meteor-reconnection-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-10-07 22:29:18 +08:00
|
|
|
const findUnauthorized = await this.hasElement(e.unauthorized);
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
|
|
|
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
2021-08-26 22:13:18 +08:00
|
|
|
} catch (err) {
|
|
|
|
await this.logger(err);
|
2021-08-14 01:35:00 +08:00
|
|
|
return false;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async triggerNetworkServiceDisconnection(testName) {
|
2021-08-14 01:35:00 +08:00
|
|
|
try {
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `01-after-audio-modal-close-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-08-14 01:35:00 +08:00
|
|
|
await sleep(5000);
|
|
|
|
await this.logger('Stopping Network Service...');
|
2021-10-01 04:20:31 +08:00
|
|
|
await exec('sh trigger/stop-network.sh', async (error, data, getter) => {
|
2021-08-14 01:35:00 +08:00
|
|
|
if (error) {
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("error", error.message);
|
2021-08-14 01:35:00 +08:00
|
|
|
return;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
2021-08-14 01:35:00 +08:00
|
|
|
if (getter) {
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("data", data);
|
2021-08-14 01:35:00 +08:00
|
|
|
return;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("data", data);
|
2021-08-14 01:35:00 +08:00
|
|
|
});
|
|
|
|
const meteorStatus = await this.page.evaluate(() => Meteor.status());
|
|
|
|
const meteorStatusConfirm = await meteorStatus.status === "offline";
|
|
|
|
await this.logger('Check if Meteor is Offline => ', meteorStatusConfirm);
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `02-after-network-service-shutdown-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.logger('Counting ', CLIENT_RECONNECTION_TIMEOUT / 6000, ' seconds...');
|
|
|
|
await sleep(CLIENT_RECONNECTION_TIMEOUT);
|
|
|
|
await this.logger('Restarting Network Service...');
|
2021-10-01 04:20:31 +08:00
|
|
|
await exec('sh trigger/restart-network.sh', async (error, data, getter) => {
|
2021-08-14 01:35:00 +08:00
|
|
|
if (error) {
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("error", error.message);
|
2021-08-14 01:35:00 +08:00
|
|
|
return;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
2021-08-14 01:35:00 +08:00
|
|
|
if (getter) {
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("data", data);
|
2021-08-14 01:35:00 +08:00
|
|
|
return;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
2021-08-14 05:43:59 +08:00
|
|
|
await this.logger("data", data);
|
2021-08-14 01:35:00 +08:00
|
|
|
});
|
2021-09-30 20:36:08 +08:00
|
|
|
await this.screenshot(`${testName}`, `03-after-network-service-restart-[${this.meetingId}]`);
|
2021-08-14 04:33:27 +08:00
|
|
|
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.page.reload();
|
|
|
|
await this.closeAudioModal();
|
2021-09-03 02:31:24 +08:00
|
|
|
const getAudioButton = await this.page.evaluate((joinAudioSelector) => {
|
|
|
|
return document.querySelectorAll(joinAudioSelector)[0].getAttribute('aria-disabled') === "true";
|
|
|
|
}, e.joinAudio)
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.logger('Check if Connections Buttons are disabled => ', getAudioButton);
|
|
|
|
await sleep(3000);
|
2021-10-07 22:29:18 +08:00
|
|
|
const findUnauthorized = await this.hasElement(e.unauthorized);
|
2021-08-14 01:35:00 +08:00
|
|
|
await this.logger('Check if Unauthorized message appears => ', findUnauthorized);
|
|
|
|
return meteorStatusConfirm && getAudioButton && findUnauthorized;
|
2021-08-26 22:13:18 +08:00
|
|
|
} catch (err) {
|
|
|
|
await this.logger(err);
|
2021-08-14 01:35:00 +08:00
|
|
|
return false;
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
|
|
|
}
|
2021-11-06 04:16:42 +08:00
|
|
|
|
|
|
|
async meteorReconnection(testName) {
|
|
|
|
try {
|
|
|
|
const checkSudo = await this.runScript('timeout -k 1 1 sudo id', {
|
|
|
|
handleOutput: (output) => output ? true : false
|
|
|
|
})
|
|
|
|
if (!checkSudo) {
|
|
|
|
await this.logger('Sudo failed: need to run this test with sudo (can be fixed by running "sudo -v" and entering the password)');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const checkTcpKill = await this.runScript('tcpkill', {
|
|
|
|
handleError: (output) => output.includes('not found') ? false : true
|
|
|
|
})
|
|
|
|
if (!checkTcpKill) {
|
|
|
|
await this.logger('tcpkill failed: must have the "dsniff" package installed');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
await this.init(true, false, testName, 'Moderator', undefined, undefined, undefined, undefined, ['--disable-http2']);
|
|
|
|
await this.screenshot(testName, '01-after-close-audio-modal');
|
|
|
|
await this.page.setRequestInterception(true);
|
|
|
|
this.page.on('request', (request) => {
|
|
|
|
const headers = request.headers();
|
|
|
|
headers['connection'] = 'close';
|
|
|
|
request.continue({
|
|
|
|
headers
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const hostname = new URL(this.page.url()).hostname;
|
|
|
|
const remoteIp = await this.runScript(`ping ${hostname}`, {
|
|
|
|
timeout: 1000,
|
|
|
|
handleOutput: (output) => {
|
|
|
|
const splitLog = output.split(/\s+/)[2];
|
|
|
|
const ip = splitLog.slice(1, -1);
|
|
|
|
|
|
|
|
return ip;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const modPid = this.browser.process().pid;
|
|
|
|
await sleep(7000);
|
|
|
|
const ipArgs = await this.runScript(`lsof -n -p ${modPid} | grep ${remoteIp}`, {
|
|
|
|
handleOutput: (output) => {
|
|
|
|
const completeLog = output.trim().split(/\s+/);
|
|
|
|
|
|
|
|
const ips = completeLog[8].split('->');
|
|
|
|
const [localIp, port] = ips[0].split(':');
|
|
|
|
|
|
|
|
return { localIp, port };
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const tcpInterface = await this.runScript(`ip addr | grep ${ipArgs.localIp}`, {
|
|
|
|
handleOutput: (output) => {
|
|
|
|
const outputArray = output.trim().split(/\s+/);
|
|
|
|
return outputArray[outputArray.length - 1];
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Media connections
|
|
|
|
await this.joinMicrophone();
|
|
|
|
await this.screenshot(testName, '02-after-join-microphone');
|
|
|
|
await this.shareWebcam(true);
|
|
|
|
await this.screenshot(testName, '03-after-share-webcam');
|
|
|
|
await screenshareUtil.startScreenshare(this);
|
|
|
|
await this.screenshot(testName, '04-after-start-screenshare');
|
|
|
|
|
|
|
|
await this.runScript(`sudo tcpkill -i ${tcpInterface} port ${ipArgs.port} and host ${remoteIp}`, { timeout: 7500 });
|
|
|
|
await this.screenshot(testName, '05-after-kill-connection');
|
|
|
|
|
|
|
|
const isTalking = await this.page.evaluate(checkElement, e.isTalking);
|
|
|
|
const isSharingWebcam = await this.page.evaluate(checkElement, e.webcamVideo);
|
|
|
|
const isSharingScreen = await this.page.evaluate(checkElement, e.stopScreenSharing);
|
|
|
|
|
|
|
|
return isTalking && isSharingWebcam && isSharingScreen;
|
|
|
|
} catch (err) {
|
|
|
|
await this.logger(err);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async runScript(script, { handleError, handleOutput, timeout }) {
|
|
|
|
return new Promise((res, rej) => {
|
|
|
|
return exec(script, { timeout }, (err, stdout, stderr) => {
|
|
|
|
res(handleError ? handleError(stderr) : handleOutput ? handleOutput(stdout) : null)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2021-06-06 22:01:37 +08:00
|
|
|
}
|
|
|
|
|
2023-04-04 04:23:26 +08:00
|
|
|
module.exports = exports = Trigger;
|