diff --git a/src/input/camera_access.js b/src/input/camera_access.js index d5f3c3a..9722001 100644 --- a/src/input/camera_access.js +++ b/src/input/camera_access.js @@ -84,7 +84,7 @@ function applyCameraFacing(facing, constraints) { }); }); } - return Promise.resolve(merge({}, videoConstraints, {facingMode: facing})); + return Promise.resolve(merge({}, constraints, {video: {facingMode: facing}})); } function pickConstraints(videoConstraints) { diff --git a/test/spec/camera_access.spec.js b/test/spec/camera_access.spec.js index df683f1..91ddf35 100644 --- a/test/spec/camera_access.spec.js +++ b/test/spec/camera_access.spec.js @@ -13,7 +13,11 @@ beforeEach(function() { originalURL = window.URL; originalMediaStreamTrack = window.MediaStreamTrack; window.MediaStreamTrack = {}; - window.URL = null; + window.URL = { + createObjectURL(stream) { + return stream; + } + }; stream = { getVideoTracks: function() { @@ -43,51 +47,119 @@ afterEach(function() { describe('success', function() { beforeEach(function() { - sinon.stub(navigator, "getUserMedia", function(constraints, success) { - success(stream); + sinon.stub(navigator.mediaDevices, "getUserMedia", function(constraints) { + return Promise.resolve(stream); }); }); afterEach(function() { - navigator.getUserMedia.restore(); + navigator.mediaDevices.getUserMedia.restore(); }); describe('request', function () { it('should request the camera', function (done) { - CameraAccess.request(video, {}, function () { - expect(navigator.getUserMedia.calledOnce).to.equal(true); + CameraAccess.request(video, {}) + .then(function () { + expect(navigator.mediaDevices.getUserMedia.calledOnce).to.equal(true); expect(video.src).to.deep.equal(stream); done(); - }); + }) + window.setTimeout(() => { + video.onloadedmetadata(); + }, 100); + }); + + it("should allow deprecated constraints to be used", (done) => { + CameraAccess.request(video, { + width: 320, + height: 240, + facing: "user", + minAspectRatio: 2, + maxAspectRatio: 100 + }) + .then(function () { + const call = navigator.mediaDevices.getUserMedia.getCall(0), + args = call.args; + expect(call).to.be.defined; + expect(args[0].video.width).to.equal(320); + expect(args[0].video.height).to.equal(240); + expect(args[0].video.facingMode).to.equal("user"); + expect(args[0].video.aspectRatio).to.equal(2); + expect(args[0].video.facing).not.to.be.defined; + expect(args[0].video.minAspectRatio).not.to.be.defined; + expect(args[0].video.maxAspectRatio).not.to.be.defined; + done(); + }) + window.setTimeout(() => { + video.onloadedmetadata(); + }, 100); + }); + }); + + describe('facingMode fallback in Chrome', () => { + beforeEach(() => { + window.MediaStreamTrack.getSources = (cb) => { + return cb([ + {kind: "video", facing: "environment", id: "environment"}, + {kind: "audio", id: "audio"}, + {kind: "video", facing: "user", id: "user"} + ]); + }; + }); + + afterEach(() => { + window.MediaStreamTrack = {}; + }) + + it("should set deviceId in case facingMode is not supported", (done) => { + CameraAccess.request(video, { + facing: "user" + }) + .then(function () { + const call = navigator.mediaDevices.getUserMedia.getCall(0), + args = call.args; + expect(call).to.be.defined; + expect(args[0].video.facingMode).not.to.be.defined; + expect(args[0].video.deviceId).to.equal("user"); + done(); + }) + window.setTimeout(() => { + video.onloadedmetadata(); + }, 100); }); }); describe('release', function () { it('should release the camera', function (done) { - CameraAccess.request(video, {}, function () { + CameraAccess.request(video, {}) + .then(function () { expect(video.src).to.deep.equal(stream); CameraAccess.release(); expect(video.src.getVideoTracks()).to.have.length(1); expect(video.src.getVideoTracks()[0].stop.calledOnce).to.equal(true); done(); }); + window.setTimeout(() => { + video.onloadedmetadata(); + }, 100); }); }); }); describe('failure', function() { describe("permission denied", function(){ - before(function() { - sinon.stub(navigator, "getUserMedia", function(constraints, success, failure) { - failure(new Error()); + beforeEach(function() { + sinon.stub(navigator.mediaDevices, "getUserMedia", function(constraints, success, failure) { + return Promise.reject(new Error()); }); }); - after(function() { - navigator.getUserMedia.restore(); + afterEach(function() { + navigator.mediaDevices.getUserMedia.restore(); }); it('should throw if getUserMedia not available', function(done) { - CameraAccess.request(video, {}, function(err) { + CameraAccess.request(video, {}) + .catch(function (err) { expect(err).to.be.defined; done(); }); @@ -97,17 +169,18 @@ describe('failure', function() { describe("not available", function(){ var originalGetUserMedia; - before(function() { - originalGetUserMedia = navigator.getUserMedia; - navigator.getUserMedia = undefined; + beforeEach(function() { + originalGetUserMedia = navigator.mediaDevices.getUserMedia; + navigator.mediaDevices.getUserMedia = undefined; }); - after(function() { - navigator.getUserMedia = originalGetUserMedia; + afterEach(function() { + navigator.mediaDevices.getUserMedia = originalGetUserMedia; }); it('should throw if getUserMedia not available', function(done) { - CameraAccess.request(video, {}, function(err) { + CameraAccess.request(video, {}) + .catch((err) => { expect(err).to.be.defined; done(); });