mirror of
https://github.com/ancsemi/Haven.git
synced 2026-10-27 00:54:56 +00:00
73 lines
2.7 KiB
JavaScript
73 lines
2.7 KiB
JavaScript
/**
|
|
* A camera's track can arrive before the webcam-started that says what it
|
|
* is. It used to be dropped, and the camera stayed invisible until someone
|
|
* reconnected; now the announcement shows the track that was waiting.
|
|
*
|
|
* node --test test/webcamClaim.test.js
|
|
*/
|
|
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
const vm = require('node:vm');
|
|
|
|
const VOICE_SOURCE = fs.readFileSync(path.join(__dirname, '..', 'public/js/voice.js'), 'utf8');
|
|
|
|
function loadVoiceManager() {
|
|
const context = vm.createContext({
|
|
module: { exports: {} },
|
|
navigator: { userAgent: '', platform: '', maxTouchPoints: 0 },
|
|
document: {},
|
|
localStorage: { getItem: () => null, setItem: () => {}, removeItem: () => {} },
|
|
console: { log() {}, warn() {}, error() {} },
|
|
MediaStream: function MediaStream(tracks) { this.tracks = tracks || []; },
|
|
setTimeout: () => 1,
|
|
clearTimeout: () => {},
|
|
});
|
|
vm.runInContext(`${VOICE_SOURCE}\nmodule.exports = VoiceManager;`, context, { filename: 'voice.js' });
|
|
return context.module.exports;
|
|
}
|
|
|
|
function viewer(VoiceManager, peer) {
|
|
const voice = Object.create(VoiceManager.prototype);
|
|
voice.peers = new Map([[7, peer]]);
|
|
voice.shown = [];
|
|
voice.onWebcamStream = (userId, stream) => voice.shown.push({ userId, stream });
|
|
return voice;
|
|
}
|
|
|
|
test('webcam-started shows a camera track that arrived first', () => {
|
|
const VoiceManager = loadVoiceManager();
|
|
const track = { kind: 'video', readyState: 'live', id: 'cam-1' };
|
|
const stream = { id: 'cam-stream' };
|
|
const peer = { _unclaimedVideo: { track, stream } };
|
|
const voice = viewer(VoiceManager, peer);
|
|
voice._claimWebcamTrack(7);
|
|
assert.equal(voice.shown.length, 1);
|
|
assert.equal(voice.shown[0].userId, 7);
|
|
assert.equal(voice.shown[0].stream, stream);
|
|
assert.equal(peer._webcamTrackId, 'cam-1', 'remembered so screen recovery skips it');
|
|
assert.equal(peer._unclaimedVideo, null);
|
|
// Later events on the track still reach the tile.
|
|
track.onended();
|
|
assert.equal(voice.shown.at(-1).stream, null);
|
|
});
|
|
|
|
test('nothing waiting, an ended track, or the screen track: no camera tile', () => {
|
|
const VoiceManager = loadVoiceManager();
|
|
const none = viewer(VoiceManager, {});
|
|
none._claimWebcamTrack(7);
|
|
none._claimWebcamTrack(99);
|
|
assert.equal(none.shown.length, 0);
|
|
|
|
const ended = viewer(VoiceManager, { _unclaimedVideo: { track: { readyState: 'ended', id: 'a' } } });
|
|
ended._claimWebcamTrack(7);
|
|
assert.equal(ended.shown.length, 0);
|
|
|
|
const screen = viewer(VoiceManager, { _screenTrackId: 's', _unclaimedVideo: { track: { readyState: 'live', id: 's' } } });
|
|
screen._claimWebcamTrack(7);
|
|
assert.equal(screen.shown.length, 0);
|
|
});
|