Merged master to 1.0

1.0
Christoph Oberhofer 8 years ago
commit 1d470660a7

@ -1,7 +1,7 @@
quaggaJS
========
- [Changelog](#changelog) (2016-08-15)
- [Changelog](#changelog) (2017-01-08)
- [Browser Support](#browser-support)
- [Installing](#installing)
- [Getting Started](#gettingstarted)
@ -65,6 +65,30 @@ browsers, meaning that `http://` can only be used on `localhost`. All other
hostnames need to be served via `https://`. You can find more information in the
[Chrome M47 WebRTC Release Notes](https://groups.google.com/forum/#!topic/discuss-webrtc/sq5CVmY69sc).
### Feature-detection of getUserMedia
Every browser seems to differently implement the `mediaDevices.getUserMedia`
API. Therefore it's highly recommended to include
[webrtc-adapter](https://github.com/webrtc/adapter) in your project.
Here's how you can test your browser's capabilities:
```javascript
if (navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia === 'function') {
// safely access `navigator.mediaDevices.getUserMedia`
}
```
The above condition evaluates to:
| Browser | result |
| ------------- |:-------:|
| Edge | `true` |
| Chrome | `true` |
| Firefox | `true` |
| IE 11 | `false` |
| Safari iOS | `false` |
## <a name="installing">Installing</a>
QuaggaJS can be installed using __npm__, __bower__, or by including it with
@ -641,6 +665,17 @@ on the ``singleChannel`` flag in the configuration when using ``decodeSingle``.
## <a name="changelog">Changelog</a>
### 2017-01-08
- Improvements
- Exposing `CameraAccess` module to get access to methods like
`enumerateVideoDevices` and `getActiveStreamLabel`
(see `example/live_w_locator`)
- Update to webpack 2.2 (API is still unstable)
### 2016-10-03
- Fixes
- Fixed `facingMode` issue with Chrome >= 53 (see [#128](https://github.com/serratus/quaggaJS/issues/128))
### 2016-08-15
- Features
- Proper handling of EXIF orientation when using `Quagga.decodeSingle`

10030
dist/quagga.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,6 +1,29 @@
.collapsable-source pre {
font-size: small;
}
@charset "UTF-8";
/* usual styles */
/* LESS - http://lesscss.org style sheet */
/* Palette color codes */
/* Palette URL: http://paletton.com/#uid=31g0q0kHZAviRSkrHLOGomVNzac */
/* Feel free to copy&paste color codes to your application */
/* MIXINS */
/* As hex codes */
/* Main Primary color */
/* Main Secondary color (1) */
/* Main Secondary color (2) */
/* As RGBa codes */
/* Main Primary color */
/* Main Secondary color (1) */
/* Main Secondary color (2) */
/* Generated by Paletton.com ├é┬® 2002-2014 */
/* http://paletton.com */
@import url("https://fonts.googleapis.com/css?family=Ubuntu:400,700|Cabin+Condensed:400,600");
/* line 1, ../sass/_viewport.scss */
#interactive.viewport {
width: 640px;
height: 480px;
}
.input-field {
display: flex;

@ -81,6 +81,11 @@
<option value="8">8</option>
</select>
</label>
<label>
<span>Camera</span>
<select name="input-stream_constraints" id="deviceSelection">
</select>
</label>
</fieldset>
</div>
<div id="result_strip">
@ -93,11 +98,12 @@
</section>
<footer>
<p>
&copy; Copyright by Christoph Oberhofer
&copy; Made with ❤️ by Christoph Oberhofer
</p>
</footer>
<script src="vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
<script src="//webrtc.github.io/adapter/adapter-latest.js" type="text/javascript"></script>
<script src="../dist/quagga.js" type="text/javascript"></script>
<script src="live_w_locator.js" type="text/javascript"></script>
</body>

@ -19,9 +19,31 @@ $(function() {
console.log("Error: " + err);
});
},
initCameraSelection: function(){
var streamLabel = Quagga.CameraAccess.getActiveStreamLabel();
return Quagga.CameraAccess.enumerateVideoDevices()
.then(function(devices) {
function pruneText(text) {
return text.length > 30 ? text.substr(0, 30) : text;
}
var $deviceSelection = document.getElementById("deviceSelection");
while ($deviceSelection.firstChild) {
$deviceSelection.removeChild($deviceSelection.firstChild);
}
devices.forEach(function(device) {
var $option = document.createElement("option");
$option.value = device.deviceId || device.id;
$option.appendChild(document.createTextNode(pruneText(device.label || device.deviceId || device.id)));
$option.selected = streamLabel === device.label;
$deviceSelection.appendChild($option);
});
});
},
attachListeners: function() {
var self = this;
self.initCameraSelection();
$(".controls").on("click", "button.stop", function(e) {
e.preventDefault();
this.detachListeners();
@ -47,8 +69,12 @@ $(function() {
return parts.reduce(function(o, key, i) {
if (setter && (i + 1) === depth) {
if (typeof o[key] === "object" && typeof val === "object") {
Object.assign(o[key], val);
} else {
o[key] = val;
}
}
return key in o ? o[key] : {};
}, obj);
},
@ -77,11 +103,16 @@ $(function() {
inputMapper: {
inputStream: {
constraints: function(value){
if (/^(\d+)x(\d+)$/.test(value)) {
var values = value.split('x');
return {
width: parseInt(values[0]),
height: parseInt(values[1])
width: {min: parseInt(values[0])},
height: {min: parseInt(values[1])}
};
}
return {
deviceId: value
};
}
},
numOfWorkers: function(value) {
@ -110,9 +141,10 @@ $(function() {
inputStream: {
type : "LiveStream",
constraints: {
width: 640,
height: 480,
facingMode: "environment"
width: {min: 640},
height: {min: 480},
facingMode: "environment",
aspectRatio: {min: 1, max: 2}
}
},
locator: {

@ -71,7 +71,7 @@
</div>
</section>
<ul class="results"></ul>
<script src="//webrtc.github.io/adapter/adapter-latest.js" type="text/javascript"></script>
<script src="../../dist/quagga.js" type="text/javascript"></script>
<script src="index.js" type="text/javascript"></script>
<script src="../vendor/prism.js"></script>

@ -43,6 +43,7 @@
</p>
</footer>
<script src="//webrtc.github.io/adapter/adapter-latest.js" type="text/javascript"></script>
<script src="static/bundle.js" type="text/javascript"></script>
<script src="../vendor/prism.js"></script>
</body>

@ -152,6 +152,7 @@ App.init();
</p>
</footer>
<script src="//webrtc.github.io/adapter/adapter-latest.js" type="text/javascript"></script>
<script src="../../dist/quagga.js" type="text/javascript"></script>
<script src="index.js" type="text/javascript"></script>
<script src="../vendor/prism.js"></script>

@ -24,6 +24,7 @@ module.exports = function(config) {
resolve: {
modules: [
path.resolve('./src/input/'),
path.resolve('./src/common/'),
'node_modules'
]
},
@ -36,7 +37,6 @@ module.exports = function(config) {
plugins: [
'karma-chrome-launcher',
'karma-mocha',
'karma-requirejs',
'karma-chai',
'karma-sinon',
'karma-sinon-chai',

@ -23,12 +23,13 @@ module.exports = function(config) {
}, {
test: /\.js$/,
include: path.resolve('src'),
loader: 'babel-istanbul'
loader: 'istanbul-instrumenter-loader'
}]
},
resolve: {
modules: [
path.resolve('./src/input/'),
path.resolve('./test/mocks/'),
'node_modules'
]
},

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -7,16 +7,16 @@
"devDependencies": {
"async": "^1.4.2",
"babel-cli": "^6.5.1",
"babel-core": "^6.7.4",
"babel-eslint": "^6.0.4",
"babel-istanbul-loader": "^0.1.0",
"babel-loader": "^6.2.4",
"babel-plugin-add-module-exports": "^0.1.2",
"babel-core": "^6.21.0",
"babel-eslint": "^7.1.1",
"babel-istanbul": "^0.8.0",
"babel-loader": "^6.2.10",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-check-es2015-constants": "^6.3.13",
"babel-plugin-lodash": "^2.2.1",
"babel-plugin-lodash": "^3.2.11",
"babel-plugin-transform-es2015-arrow-functions": "^6.3.13",
"babel-plugin-transform-es2015-block-scoped-functions": "^6.3.13",
"babel-plugin-transform-es2015-block-scoping": "^6.3.13",
"babel-plugin-transform-es2015-block-scoping": "^6.21.0",
"babel-plugin-transform-es2015-classes": "^6.3.13",
"babel-plugin-transform-es2015-computed-properties": "^6.3.13",
"babel-plugin-transform-es2015-destructuring": "^6.3.13",
@ -25,7 +25,7 @@
"babel-plugin-transform-es2015-literals": "^6.3.13",
"babel-plugin-transform-es2015-modules-commonjs": "^6.3.13",
"babel-plugin-transform-es2015-object-super": "^6.3.13",
"babel-plugin-transform-es2015-parameters": "^6.3.13",
"babel-plugin-transform-es2015-parameters": "^6.21.0",
"babel-plugin-transform-es2015-shorthand-properties": "^6.3.13",
"babel-plugin-transform-es2015-spread": "^6.3.13",
"babel-plugin-transform-es2015-sticky-regex": "^6.3.13",
@ -33,35 +33,36 @@
"babel-plugin-transform-es2015-typeof-symbol": "^6.3.13",
"babel-plugin-transform-es2015-unicode-regex": "^6.3.13",
"babel-plugin-transform-object-rest-spread": "^6.5.0",
"babel-plugin-transform-regenerator": "^6.3.13",
"babel-plugin-transform-regenerator": "^6.21.0",
"chai": "^3.4.1",
"core-js": "^1.2.1",
"cross-env": "^1.0.7",
"core-js": "^2.4.1",
"cross-env": "^3.1.4",
"eslint": "^1.10.3",
"eslint-plugin-react": "^5.1.1",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-contrib-nodeunit": "^0.4.1",
"grunt-karma": "^0.12.1",
"grunt-karma": "^2.0.0",
"isparta-loader": "^2.0.0",
"karma": "^0.13.9",
"istanbul-instrumenter-loader": "^2.0.0",
"karma": "^1.3.0",
"karma-chai": "0.1.0",
"karma-chrome-launcher": "^0.2.0",
"karma-coverage": "^0.5.2",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^0.1.7",
"karma-mocha": "~0.2.0",
"karma-phantomjs-launcher": "^0.2.1",
"karma-sinon": "^1.0.4",
"karma-sinon-chai": "^1.1.0",
"karma-source-map-support": "^1.1.0",
"karma-webpack": "^1.7.0",
"karma-webpack": "^1.8.1",
"lolex": "^1.4.0",
"mocha": "^2.3.2",
"phantomjs": "^1.9.18",
"sinon": "^1.16.1",
"sinon": "^1.17.7",
"sinon-chai": "^2.8.0",
"webpack": "2.1.0-beta.4",
"webpack-sources": "^0.1.1"
"webpack": "^2.2.1",
"webpack-sources": "^0.1.4"
},
"directories": {
"doc": "doc"
@ -106,9 +107,8 @@
"gl-mat2": "^1.0.0",
"gl-vec2": "^1.0.0",
"gl-vec3": "^1.0.3",
"lodash": "^4.6.1",
"lodash": "^4.17.4",
"ndarray": "^1.0.18",
"ndarray-linear-interpolate": "^1.0.0",
"webrtc-adapter": "^2.0.2"
"ndarray-linear-interpolate": "^1.0.0"
}
}

@ -0,0 +1,33 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC9ORap3LvRegtrhRc8dLdH9Bp2QokcKEsWbtvyhtjisRRm2slK
A6Q11McB/YTb7oImFfNaCX+7vdM1oVXVLJ0ekQaNljXG5Dy7DXEcT1V6gpN4xmZJ
8f/KZ45VBINN0Ha74L7nS4kgImh5yvNolNr4IdlSjGf09kciFy8S3kPlGQIDAQAB
AoGAYDlaxBCC1liY3Bl3IoA7//QrTL4zGUWIQaUoZmGag1UHifJycBf/9nv4o5N3
b5wPRSzebofsE93JPTmI+3nPf62k5rS2xOo8swwOZc+f5/v0EnUNixD7P0jBiLVR
B8kbMvNdNn33HuynW1/MSBFE0cfeDH2i8SVl+Z+fHYIUW10CQQD0yWB8xeM8AxYB
/ZZWClem6gf1lQAYLzid3x51pkLqRFpX+rG251cSBUouE+kVO14j2xrBqCyyOwNu
17eazy3DAkEAxeQdWP9b11ihKOf/kjXiczltLnBsotn6K9EEAe0QuH/6iXLm86mL
ZiQe+TrY1GWbK3ns0sfXgNJ2aeaRkeZn8wJAWF5WedTKisCmckOEwTzslbJI+0w2
A4UQkFWa3mgOIhpY7wfunhP35+aG+AlyDJspChKwHxdCQ3lwbNRtUPLYFwJBAK8G
9QIbUbLlPB1/HOfH6xM4rp3NZ/idzQxmISJG+GwHHaPmUekfgyEDP7X2W4N4nsbU
XyeLA8t32q4N9aDS5gsCQDHqhsXqnY6e4IEZrvf90l2V1PpnTKfEl/F5wye3g69G
JN57scVUBHP/KKoyfge0fytWiQN/56KvWH+G5+N/JyA=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC2zCCAkSgAwIBAgIJALUDN95Or7XlMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
BAYTAkFUMQ8wDQYDVQQIEwZTdHlyaWExDTALBgNVBAcTBEdyYXoxETAPBgNVBAoT
CFF1YWdnYUpTMREwDwYDVQQDEwhxdWFnZ2FqczAeFw0xNzAxMDgxNjI5MjhaFw0x
ODAxMDgxNjI5MjhaMFMxCzAJBgNVBAYTAkFUMQ8wDQYDVQQIEwZTdHlyaWExDTAL
BgNVBAcTBEdyYXoxETAPBgNVBAoTCFF1YWdnYUpTMREwDwYDVQQDEwhxdWFnZ2Fq
czCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvTkWqdy70XoLa4UXPHS3R/Qa
dkKJHChLFm7b8obY4rEUZtrJSgOkNdTHAf2E2+6CJhXzWgl/u73TNaFV1SydHpEG
jZY1xuQ8uw1xHE9VeoKTeMZmSfH/ymeOVQSDTdB2u+C+50uJICJoecrzaJTa+CHZ
Uoxn9PZHIhcvEt5D5RkCAwEAAaOBtjCBszAdBgNVHQ4EFgQUYm5+uJVOOGiYa+Vx
2o++VHyWkwIwgYMGA1UdIwR8MHqAFGJufriVTjhomGvlcdqPvlR8lpMCoVekVTBT
MQswCQYDVQQGEwJBVDEPMA0GA1UECBMGU3R5cmlhMQ0wCwYDVQQHEwRHcmF6MREw
DwYDVQQKEwhRdWFnZ2FKUzERMA8GA1UEAxMIcXVhZ2dhanOCCQC1AzfeTq+15TAM
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACyzC/CKL1mgTuNgFDuUf6u+
YMnqlc9wcnEaFuvXnkSh6fT+qMZm188C/tlZwcWTrGmoCM0K6mX1TpHOjm8vbeXZ
diezAVGIVN3VoHqm6yJldI2rgFI9r5BfwAWYC8XNjqnT3U6cm4k8iC7jmLC+dT9r
Ysx2ucAF6lNHayekRmNq
-----END CERTIFICATE-----

@ -0,0 +1,30 @@
# taken from http://www.piware.de/2011/01/creating-an-https-server-in-python/
# generate server.xml with the following command:
# openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
# run as follows:
# python simple-https-server.py
# then in your browser, visit:
# https://localhost:4443
import BaseHTTPServer, SimpleHTTPServer
import ssl
import sys, getopt
host = 'localhost'
port = 4443
try:
opts, args = getopt.getopt(sys.argv[1:],"",["host=", "port="])
except getopt.GetoptError:
print 'simple-https-server.py --host <host> --port <port>'
sys.exit(2)
for opt, arg in opts:
if opt in ("--host"):
host = arg
elif opt in ("--port"):
port = int(arg)
print 'host is ', host
print 'port is ', port
httpd = BaseHTTPServer.HTTPServer((host, port), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
httpd.serve_forever()

@ -0,0 +1,17 @@
export function enumerateDevices() {
if (navigator.mediaDevices
&& typeof navigator.mediaDevices.enumerateDevices === 'function') {
return navigator.mediaDevices.enumerateDevices();
}
return Promise.reject(new Error('enumerateDevices is not defined'));
};
export function getUserMedia(constraints) {
if (navigator.mediaDevices
&& typeof navigator.mediaDevices.getUserMedia === 'function') {
return navigator.mediaDevices
.getUserMedia(constraints);
}
return Promise.reject(new Error('getUserMedia is not defined'));
}

@ -24,3 +24,28 @@ Math.imul = Math.imul || function(a, b) {
// the final |0 converts the unsigned value into a signed value
return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0);
};
if (typeof Object.assign !== 'function') {
Object.assign = function(target) { // .length of function is 2
'use strict';
if (target === null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource !== null) { // Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
};
}

@ -1,4 +1,10 @@
import {pick} from 'lodash';
import {omit, pick} from 'lodash';
import {getUserMedia, enumerateDevices} from 'mediaDevices';
const facingMatching = {
"user": /front/i,
"environment": /back/i
};
var streamRef;
@ -32,10 +38,7 @@ function waitForVideo(video) {
* @param {Object} video
*/
function initCamera(video, constraints) {
if (navigator.mediaDevices
&& typeof navigator.mediaDevices.getUserMedia === 'function') {
return navigator.mediaDevices
.getUserMedia(constraints)
return getUserMedia(constraints)
.then((stream) => {
return new Promise((resolve) => {
streamRef = stream;
@ -48,8 +51,6 @@ function initCamera(video, constraints) {
});
})
.then(waitForVideo.bind(null, video));
}
return Promise.reject(new Error('getUserMedia is not defined'));
}
function deprecatedConstraints(videoConstraints) {
@ -68,16 +69,28 @@ function deprecatedConstraints(videoConstraints) {
return normalized;
}
function pickConstraints(videoConstraints) {
return {
export function pickConstraints(videoConstraints) {
const normalizedConstraints = {
audio: false,
video: deprecatedConstraints(videoConstraints)
};
if (normalizedConstraints.video.deviceId
&& normalizedConstraints.video.facingMode) {
delete normalizedConstraints.video.facingMode;
}
return Promise.resolve(normalizedConstraints);
}
function enumerateVideoDevices() {
return enumerateDevices()
.then(devices => devices.filter(device => device.kind === 'videoinput'));
}
export default {
request: function(video, videoConstraints) {
return initCamera(video, pickConstraints(videoConstraints));
return pickConstraints(videoConstraints)
.then(initCamera.bind(null, video));
},
release: function() {
var tracks = streamRef && streamRef.getVideoTracks();
@ -85,5 +98,14 @@ export default {
tracks[0].stop();
}
streamRef = null;
},
enumerateVideoDevices,
getActiveStreamLabel: function() {
if (streamRef) {
const tracks = streamRef.getVideoTracks();
if (tracks && tracks.length) {
return tracks[0].label;
}
}
}
};

@ -1,5 +1,4 @@
import './common/typedefs';
import 'webrtc-adapter';
import createScanner from './scanner';
import ImageWrapper from './common/image_wrapper';
import ImageDebug from './common/image_debug';
@ -134,4 +133,5 @@ function createApi(configuration = Config) {
}
};
}
export default createApi();

@ -10,9 +10,9 @@ module.exports = function(grunt) {
grunt.registerTask('uglyasm', function() {
var code = fs.readFileSync('dist/quagga.js', 'utf-8'),
minifiedCode = fs.readFileSync('dist/quagga.min.js', 'utf-8'),
commentEnd = '/* @preserve ASM END */',
moduleFunctionRegex = /function\s*\((\w+,\s*\w+,\s*\w+)\)\s*\{\s*\/\* \@preserve ASM BEGIN \*\//,
commentStartIdx = code.indexOf("/* @preserve ASM BEGIN */"),
commentEnd = '@preserve ASM END',
moduleFunctionRegex = /function\s*\((\w+,\s*\w+,\s*\w+)\)\s*\{(\n?\s*\"use strict\";?)*\n?\/\*\s*\@preserve ASM BEGIN/,
commentStartIdx = code.indexOf("@preserve ASM BEGIN"),
asmEndIdxTmp = code.indexOf(commentEnd),
asmEndIdx = code.indexOf("}", asmEndIdxTmp),
asmCodeTmp = code.substring(commentStartIdx - Math.min(500, commentStartIdx),
@ -30,8 +30,6 @@ module.exports = function(grunt) {
.replace(/ ([+=^|&]|>+|<+) /g, '$1') // remove spaces around operators
.replace(/[\r\n/]/g, ''); // remove new lines
grunt.log.debug(asmCodeMinified);
asmModule = moduleFunctionRegex.exec(asmCode);
if (!asmModule) {
grunt.log.error("No ASM module found");

@ -0,0 +1,36 @@
let devices = [],
stream,
_constraints,
_supported = true;
export function enumerateDevices() {
console.log("enumerateDevices!!!!");
return Promise.resolve(devices);
};
export function getUserMedia(constraints) {
console.log("getUserMedia!!!!");
_constraints = constraints;
if (_supported) {
return Promise.resolve(stream);
}
return Promise.reject(new Error("das"));
}
export function setDevices(newDevices) {
devices = [...newDevices];
}
export function setStream(newStream) {
stream = newStream;
}
export function getConstraints() {
return _constraints;
}
export function setSupported(supported) {
console.log("Supported: " + supported);
_supported = supported;
}

@ -1,4 +1,5 @@
import CameraAccess from '../../src/input/camera_access';
import CameraAccess, {pickConstraints} from '../../src/input/camera_access';
import {setDevices, setStream, getConstraints, setSupported} from 'mediaDevices';
var originalURL,
originalMediaStreamTrack,
@ -15,7 +16,7 @@ describe("CameraAccess", () => {
originalMediaStreamTrack = window.MediaStreamTrack;
window.MediaStreamTrack = {};
window.URL = {
createObjectURL() {
createObjectURL(stream) {
return stream;
}
};
@ -25,6 +26,7 @@ describe("CameraAccess", () => {
return tracks;
}
};
setStream(stream);
sinon.spy(tracks[0], "stop");
video = {
@ -57,6 +59,7 @@ describe("CameraAccess", () => {
afterEach(function() {
navigator.mediaDevices.getUserMedia.restore();
});
describe('request', function () {
it('should request the camera', function (done) {
CameraAccess.request(video, {})
@ -91,6 +94,7 @@ describe("CameraAccess", () => {
});
});
describe('release', function () {
it('should release the camera', function (done) {
CameraAccess.request(video, {})
.then(function () {
@ -102,19 +106,18 @@ describe("CameraAccess", () => {
});
});
});
});
describe('failure', function() {
describe("permission denied", function(){
beforeEach(function() {
sinon.stub(navigator.mediaDevices, "getUserMedia", function(constraints, success, failure) {
return Promise.reject(new Error());
});
beforeEach(() => {
setSupported(false);
});
afterEach(function() {
navigator.mediaDevices.getUserMedia.restore();
afterEach(() => {
setSupported(true);
});
describe("permission denied", function(){
it('should throw if getUserMedia not available', function(done) {
CameraAccess.request(video, {})
.catch(function (err) {
@ -144,5 +147,48 @@ describe("CameraAccess", () => {
});
});
});
describe("pickConstraints", () => {
it("should return the given constraints if no facingMode is defined", (done) => {
const givenConstraints = {width: 180};
return pickConstraints(givenConstraints).then((actualConstraints) => {
expect(actualConstraints.video).to.deep.equal(givenConstraints);
done();
})
.catch((err) => {
expect(err).to.equal(null);
console.log(err);
done();
});
});
it("should return the given constraints if deviceId is defined", (done) => {
const givenConstraints = {width: 180, deviceId: "4343"};
return pickConstraints(givenConstraints).then((actualConstraints) => {
expect(actualConstraints.video).to.deep.equal(givenConstraints);
done();
})
.catch((err) => {
expect(err).to.equal(null);
console.log(err);
done();
});
});
it("should set deviceId if facingMode is set to environment", (done) => {
setDevices([{deviceId: "front", kind: "videoinput", label: "front Facing"},
{deviceId: "back", label: "back Facing", kind: "videoinput"}]);
const givenConstraints = {width: 180, facingMode: "environment"};
return pickConstraints(givenConstraints).then((actualConstraints) => {
expect(actualConstraints.video).to.deep.equal({width: 180, deviceId: "back"});
done();
})
.catch((err) => {
console.log(err);
expect(err).to.equal(null);
done();
});
});
});
});
});

@ -72,7 +72,6 @@ describe("ResultCollector", () => {
results = collector.getResults();
expect(results).to.have.length(2);
results.forEach(function(result) {
expect(result).not.to.deep.equal(config.blacklist[0]);
});

@ -17,6 +17,7 @@ module.exports = {
resolve: {
modules: [
path.resolve('./src/input/'),
path.resolve('./src/common/'),
'node_modules'
]
},

@ -10,14 +10,11 @@ module.exports.plugins = module.exports.plugins.concat([
compress: {
warnings: false
},
output: {
comments: /@preserve/
},
sourceMap: false
}),
]);
module.exports.output.filename = 'quagga.min.js';
module.exports.output.sourceMapFilename = null;
module.exports.devtool = null;
module.exports.output.sourceMapFilename = '';
module.exports.devtool = false;

@ -6,6 +6,7 @@ module.exports = require('./webpack.config.js');
module.exports.resolve = {
modules: [
path.resolve('./lib/'),
path.resolve('./src/common/'),
'node_modules'
]
};

Loading…
Cancel
Save