Compare commits

..

5 Commits

Author SHA1 Message Date
damencho
11a6e94541 debug: longer waits 2. 2025-08-19 16:59:38 -05:00
damencho
e1e262fb68 debug: longer wait. 2025-08-19 16:31:03 -05:00
damencho
b0a96b32d2 fix(jiconop): Fixes loading it under different virtual hosts. 2025-08-19 15:59:34 -05:00
bgrozev
dac9b5e244 test: Check for send/receive independently. (#16356)
This allows the logs to show which one definitely failed.
2025-08-19 15:31:52 -05:00
damencho
d15cfd845a fix(config): Drops legacy config prejoinPageEnabled. 2025-08-19 08:41:04 -05:00
16 changed files with 62 additions and 66 deletions

View File

@@ -791,7 +791,6 @@ var config = {
// Configs for prejoin page.
// prejoinConfig: {
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
// // This replaces `prejoinPageEnabled`. Defaults to true.
// enabled: true,
// // Hides the participant name editing field in the prejoin screen.
// // If requireDisplayName is also set as true, a name should still be provided through

View File

@@ -521,7 +521,6 @@ export interface IConfig {
preCallTestEnabled?: boolean;
preCallTestICEUrl?: string;
};
prejoinPageEnabled?: boolean;
raisedHands?: {
disableLowerHandByModerator?: boolean;
disableLowerHandNotification?: boolean;

View File

@@ -202,7 +202,6 @@ export default [
'prejoinConfig.enabled',
'prejoinConfig.hideDisplayName',
'prejoinConfig.hideExtraJoinButtons',
'prejoinPageEnabled',
'raisedHands',
'recordingService',
'requireDisplayName',

View File

@@ -375,8 +375,7 @@ export function setConfigFromURLParams(
// When not in an iframe, start without media if the pre-join page is not enabled.
if (!isEmbedded()
&& ('config.prejoinConfig.enabled' in params || 'config.prejoinPageEnabled' in params)
&& (config.prejoinConfig?.enabled === false || config.prejoinPageEnabled === false)) {
&& 'config.prejoinConfig.enabled' in params && config.prejoinConfig?.enabled === false) {
logger.warn('Using prejoinConfig.enabled config URL overwrite implies starting without media.');
config.disableInitialGUM = true;
}

View File

@@ -405,11 +405,6 @@ function _translateLegacyConfig(oldValue: IConfig) {
newValue.welcomePage.disabled = !oldValue.enableWelcomePage;
}
newValue.prejoinConfig = oldValue.prejoinConfig || {};
if (oldValue.hasOwnProperty('prejoinPageEnabled')) {
newValue.prejoinConfig.enabled = oldValue.prejoinPageEnabled;
}
newValue.disabledSounds = newValue.disabledSounds || [];
if (oldValue.disableJoinLeaveSounds) {

View File

@@ -7,6 +7,12 @@ local services_xml = ext_services.services_xml;
-- gathers needed information and pushes it with a message to clients
-- this way we skip 4 request responses during every client setup
local main_virtual_host = module:get_option_string('muc_mapper_domain_base');
if not main_virtual_host then
module:log('warn', 'No muc_mapper_domain_base option set.');
return;
end
local shard_name_config = module:get_option_string('shard_name');
if shard_name_config then
module:add_identity("server", "shard", shard_name_config);
@@ -33,7 +39,8 @@ module:hook("resource-bind", function (event)
-- disco info data / all identity and features
local query = st.stanza("query", { xmlns = "http://jabber.org/protocol/disco#info" });
local done = {};
for _,identity in ipairs(module:get_host_items("identity")) do
-- to lod this module in different virtual hosts than the main, make sure we query here for main
for _,identity in ipairs(module:context(main_virtual_host):get_host_items("identity")) do
local identity_s = identity.category.."\0"..identity.type;
if not done[identity_s] then
query:tag("identity", identity):up();

View File

@@ -37,13 +37,6 @@ export const P2 = 'p2';
export const P3 = 'p3';
export const P4 = 'p4';
interface IWaitForSendReceiveDataOptions {
checkReceive?: boolean;
checkSend?: boolean;
msg?: string;
timeout?: number;
}
/**
* Participant.
*/
@@ -425,37 +418,50 @@ export class Participant {
}
/**
* Waits for send and receive data.
* Waits until the conference stats show positive upload and download bitrate (independently).
*
* @param {Object} options
* @param {boolean} options.checkSend - If true we will chec
* @returns {Promise<boolean>}
*/
waitForSendReceiveData({
checkSend = true,
checkReceive = true,
timeout = 15_000,
msg
} = {} as IWaitForSendReceiveDataOptions): Promise<boolean> {
if (!checkSend && !checkReceive) {
return Promise.resolve(true);
}
async waitForSendReceiveData(timeout = 15_000, msg?: string): Promise<boolean> {
const values = await Promise.all([
await this.waitForSendMedia(timeout, msg ? `${msg} (send)` : undefined),
await this.waitForReceiveMedia(timeout, msg ? `${msg} (receive)` : undefined)
]);
const lMsg = msg ?? `expected to ${
checkSend && checkReceive ? 'receive/send' : checkSend ? 'send' : 'receive'} data in 15s for ${this.name}`;
return values[0] && values[1];
}
return this.driver.waitUntil(() => this.execute((pCheckSend: boolean, pCheckReceive: boolean) => {
const stats = APP?.conference?.getStats();
const bitrateMap = stats?.bitrate || {};
const rtpStats = {
uploadBitrate: bitrateMap.upload || 0,
downloadBitrate: bitrateMap.download || 0
};
/**
* Waits until the conference stats show positive upload bitrate.
* @param timeout max time to wait in ms
* @param timeoutMsg the message to log if the timeout is reached
*/
async waitForSendMedia(
timeout = 15_000,
timeoutMsg = `expected to send media in ${timeout / 1000}s for ${this.name}`): Promise<boolean> {
return (rtpStats.uploadBitrate > 0 || !pCheckSend) && (rtpStats.downloadBitrate > 0 || !pCheckReceive);
}, checkSend, checkReceive), {
return this.driver.waitUntil(() => this.execute(() => {
return APP?.conference?.getStats()?.bitrate?.upload > 0;
}), {
timeout,
timeoutMsg: lMsg
timeoutMsg
});
}
/**
* Waits until the conference stats show positive upload bitrate.
* @param timeout max time to wait in ms
* @param timeoutMsg the message to log if the timeout is reached
*/
async waitForReceiveMedia(
timeout = 15_000,
timeoutMsg = `expected to receive media in ${timeout / 1000}s for ${this.name}`): Promise<boolean> {
return this.driver.waitUntil(() => this.execute(() => {
return APP?.conference?.getStats()?.bitrate?.download > 0;
}), {
timeout,
timeoutMsg
});
}

View File

@@ -116,7 +116,7 @@ async function muteP1BeforeP2JoinsAndScreenshare(p2p: boolean) {
await p2.waitForIceConnected();
}
await p2.waitForSendReceiveData({ checkReceive: false });
await p2.waitForSendMedia();
// Check if p1 appears video muted on p2.
await p2.getParticipantsPane().assertVideoMuteIconIsDisplayed(p1);

View File

@@ -53,7 +53,7 @@ describe('StartMuted', () => {
const p2EndpointId = await p2.getEndpointId();
await p2.waitForIceConnected();
await p2.waitForSendReceiveData({ checkSend: false });
await p2.waitForReceiveMedia();
await p2.getFilmstrip().assertAudioMuteIconIsDisplayed(p2);
await p2.getParticipantsPane().assertVideoMuteIconIsDisplayed(p2);
@@ -88,7 +88,7 @@ describe('StartMuted', () => {
const { p3 } = ctx;
await p3.waitForIceConnected();
await p3.waitForSendReceiveData({ checkSend: false });
await p3.waitForReceiveMedia();
await p3.getFilmstrip().assertAudioMuteIconIsDisplayed(p2, true);
await p3.getParticipantsPane().assertVideoMuteIconIsDisplayed(p2, true);
@@ -118,7 +118,7 @@ describe('StartMuted', () => {
const { p2 } = ctx;
await p2.waitForIceConnected();
await p2.waitForSendReceiveData({ checkSend: false });
await p2.waitForReceiveMedia();
await joinThirdParticipant({
...options,
@@ -128,7 +128,7 @@ describe('StartMuted', () => {
const { p3 } = ctx;
await p3.waitForIceConnected();
await p3.waitForSendReceiveData({ checkSend: false });
await p3.waitForReceiveMedia();
const { p1 } = ctx;
@@ -240,7 +240,7 @@ describe('StartMuted', () => {
const { p1, p2 } = ctx;
await p2.waitForIceConnected();
await p2.waitForSendReceiveData({ checkReceive: false });
await p2.waitForSendMedia();
await p2.waitForAudioMuted(p1, true);
await p2.getParticipantsPane().assertVideoMuteIconIsDisplayed(p1);

View File

@@ -23,7 +23,7 @@ describe('lastN', () => {
const { p3 } = ctx;
const p3Toolbar = p3.getToolbar();
await p3.waitForSendReceiveData({ checkReceive: false });
await p3.waitForSendMedia();
await ctx.p1.waitForRemoteVideo(await p3.getEndpointId());

View File

@@ -24,10 +24,7 @@ export async function waitForAudioFromDialInParticipant(participant: Participant
await participant.waitForIceConnected();
await participant.waitForRemoteStreams(1);
await participant.waitForSendReceiveData({
timeout: 20_000,
msg: 'dial-in.test.jigasi.participant.no.audio.after.join'
});
await participant.waitForSendReceiveData(20_000, 'dial-in.test.jigasi.participant.no.audio.after.join');
console.log(`dial-in.test.jigasi.participant.received.audio.after.join:${performance.now() - joinedTS} ms.`);
}

View File

@@ -146,7 +146,7 @@ describe('Chat', () => {
preAuthenticatedLink: string;
};
eventType: string;
} = await webhooksProxy.waitForEvent('CHAT_UPLOADED', 20000);
} = await webhooksProxy.waitForEvent('CHAT_UPLOADED', 120000);
expect('CHAT_UPLOADED').toBe(event.eventType);
expect(event.data.preAuthenticatedLink).toBeDefined();

View File

@@ -114,7 +114,7 @@ describe('Invite iframeAPI', () => {
sipAddress: string;
};
eventType: string;
} = await webhooksProxy.waitForEvent('SIP_CALL_OUT_STARTED');
} = await webhooksProxy.waitForEvent('SIP_CALL_OUT_STARTED', 120000);
expect('SIP_CALL_OUT_STARTED').toBe(sipCallOutStartedEvent.eventType);
expect(sipCallOutStartedEvent.data.sipAddress).toBe(`sip:${process.env.SIP_JIBRI_DIAL_OUT_URL}`);
@@ -201,7 +201,7 @@ async function checkDialEvents(participant: Participant, direction: string, star
participantJid: string;
};
eventType: string;
} = await webhooksProxy.waitForEvent(endedEventName);
} = await webhooksProxy.waitForEvent(endedEventName, 120000);
expect(endedEventName).toBe(dialInEndedEvent.eventType);
expect(dialInEndedEvent.customerId).toBe(customerId);

View File

@@ -98,7 +98,7 @@ describe('Recording', () => {
const liveStreamEvent: {
customerId: string;
eventType: string;
} = await webhooksProxy.waitForEvent('LIVE_STREAM_ENDED', 20000);
} = await webhooksProxy.waitForEvent('LIVE_STREAM_ENDED', 120000);
expect('LIVE_STREAM_ENDED').toBe(liveStreamEvent.eventType);
expect(liveStreamEvent.customerId).toBe(customerId);

View File

@@ -47,10 +47,8 @@ describe('Visitors', () => {
const { p1, p2, webhooksProxy } = ctx;
await p2.waitForSendReceiveData({
checkSend: false,
msg: 'Visitor is not receiving media'
}).then(() => p2.waitForRemoteStreams(1));
await p2.waitForReceiveMedia(15_000, 'Visitor is not receiving media');
await p2.waitForRemoteStreams(1);
const p2Visitors = p2.getVisitors();
const p1Visitors = p1.getVisitors();

View File

@@ -67,11 +67,8 @@ describe('Visitors', () => {
await p1Visitors.goLive();
await p2.waitToJoinMUC();
await p2.waitForSendReceiveData({
checkSend: false,
msg: 'Visitor is not receiving media'
}).then(() => p2.waitForRemoteStreams(1));
await p2.waitForReceiveMedia(15000, 'Visitor is not receiving media');
await p2.waitForRemoteStreams(1);
await p2.driver.waitUntil(() => p2Visitors.hasVisitorsDialog(), {
timeout: 5000,