mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
149 lines
5.2 KiB
JavaScript
149 lines
5.2 KiB
JavaScript
'use strict';
|
|
|
|
// Test is based on the following editor draft:
|
|
// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
|
|
|
|
// Code using this helper should also include RTCPeerConnection-helper.js
|
|
// in the main HTML file
|
|
|
|
// The following helper functions are called from RTCPeerConnection-helper.js:
|
|
// getTrackFromUserMedia
|
|
// exchangeOfferAnswer
|
|
|
|
// Create a RTCDTMFSender using getUserMedia()
|
|
// Connect the PeerConnection to another PC and wait until it is
|
|
// properly connected, so that DTMF can be sent.
|
|
function createDtmfSender(pc = new RTCPeerConnection()) {
|
|
let dtmfSender;
|
|
return getTrackFromUserMedia('audio')
|
|
.then(([track, mediaStream]) => {
|
|
const sender = pc.addTrack(track, mediaStream);
|
|
dtmfSender = sender.dtmf;
|
|
assert_true(dtmfSender instanceof RTCDTMFSender,
|
|
'Expect audio sender.dtmf to be set to a RTCDTMFSender');
|
|
// Note: spec bug open - https://github.com/w3c/webrtc-pc/issues/1774
|
|
// on whether sending should be possible before negotiation.
|
|
const pc2 = new RTCPeerConnection();
|
|
Object.defineProperty(pc, 'otherPc', { value: pc2 });
|
|
exchangeIceCandidates(pc, pc2);
|
|
return exchangeOfferAnswer(pc, pc2);
|
|
}).then(() => {
|
|
if (!('canInsertDTMF' in dtmfSender)) {
|
|
return Promise.resolve();
|
|
}
|
|
// Wait until dtmfSender.canInsertDTMF becomes true.
|
|
// Up to 150 ms has been observed in test. Wait 1 second
|
|
// in steps of 10 ms.
|
|
// Note: Using a short timeout and rejected promise in order to
|
|
// make test return a clear error message on failure.
|
|
return new Promise((resolve, reject) => {
|
|
let counter = 0;
|
|
step_timeout(function checkCanInsertDTMF() {
|
|
if (dtmfSender.canInsertDTMF) {
|
|
resolve();
|
|
} else {
|
|
if (counter >= 100) {
|
|
reject('Waited too long for canInsertDTMF');
|
|
return;
|
|
}
|
|
++counter;
|
|
step_timeout(checkCanInsertDTMF, 10);
|
|
}
|
|
}, 0);
|
|
});
|
|
}).then(() => {
|
|
return dtmfSender;
|
|
});
|
|
}
|
|
|
|
/*
|
|
Create an RTCDTMFSender and test tonechange events on it.
|
|
testFunc
|
|
Test function that is going to manipulate the DTMFSender.
|
|
It will be called with:
|
|
t - the test object
|
|
sender - the created RTCDTMFSender
|
|
pc - the associated RTCPeerConnection as second argument.
|
|
toneChanges
|
|
Array of expected tonechange events fired. The elements
|
|
are array of 3 items:
|
|
expectedTone
|
|
The expected character in event.tone
|
|
expectedToneBuffer
|
|
The expected new value of dtmfSender.toneBuffer
|
|
expectedDuration
|
|
The rough time since beginning or last tonechange event
|
|
was fired.
|
|
desc
|
|
Test description.
|
|
*/
|
|
function test_tone_change_events(testFunc, toneChanges, desc) {
|
|
// Convert to cumulative time
|
|
let cumulativeTime = 0;
|
|
const cumulativeToneChanges = toneChanges.map(c => {
|
|
cumulativeTime += c[2];
|
|
return [c[0], c[1], cumulativeTime];
|
|
});
|
|
|
|
// Wait for same duration as last expected duration + 100ms
|
|
// before passing test in case there are new tone events fired,
|
|
// in which case the test should fail.
|
|
const lastWait = toneChanges.pop()[2] + 100;
|
|
|
|
promise_test(async t => {
|
|
const pc = new RTCPeerConnection();
|
|
const dtmfSender = await createDtmfSender(pc);
|
|
const start = Date.now();
|
|
|
|
const allEventsReceived = new Promise(resolve => {
|
|
const onToneChange = t.step_func(ev => {
|
|
assert_true(ev instanceof RTCDTMFToneChangeEvent,
|
|
'Expect tone change event object to be an RTCDTMFToneChangeEvent');
|
|
|
|
const { tone } = ev;
|
|
assert_equals(typeof tone, 'string',
|
|
'Expect event.tone to be the tone string');
|
|
|
|
assert_greater_than(cumulativeToneChanges.length, 0,
|
|
'More tonechange event is fired than expected');
|
|
|
|
const [
|
|
expectedTone, expectedToneBuffer, expectedTime
|
|
] = cumulativeToneChanges.shift();
|
|
|
|
assert_equals(tone, expectedTone,
|
|
`Expect current event.tone to be ${expectedTone}`);
|
|
|
|
assert_equals(dtmfSender.toneBuffer, expectedToneBuffer,
|
|
`Expect dtmfSender.toneBuffer to be updated to ${expectedToneBuffer}`);
|
|
|
|
// We check that the cumulative delay is at least the expected one, but
|
|
// system load may cause random delays, so we do not put any
|
|
// realistic upper bound on the timing of the events.
|
|
assert_between_inclusive(Date.now() - start, expectedTime,
|
|
expectedTime + 4000,
|
|
`Expect tonechange event for "${tone}" to be fired approximately after ${expectedTime} milliseconds`);
|
|
if (cumulativeToneChanges.length === 0) {
|
|
resolve();
|
|
}
|
|
});
|
|
|
|
dtmfSender.addEventListener('tonechange', onToneChange);
|
|
});
|
|
|
|
testFunc(t, dtmfSender, pc);
|
|
await allEventsReceived;
|
|
const wait = ms => new Promise(resolve => t.step_timeout(resolve, ms));
|
|
await wait(lastWait);
|
|
}, desc);
|
|
}
|
|
|
|
// Get the one and only tranceiver from pc.getTransceivers().
|
|
// Assumes that there is only one tranceiver in pc.
|
|
function getTransceiver(pc) {
|
|
const transceivers = pc.getTransceivers();
|
|
assert_equals(transceivers.length, 1,
|
|
'Expect there to be only one tranceiver in pc');
|
|
|
|
return transceivers[0];
|
|
}
|