Compare commits

...

3 Commits

Author SHA1 Message Date
668acf2698 Add karma to run unit tests 2018-05-29 23:11:43 +01:00
7042491257 Add Dockerfile for Travis 2018-05-29 22:39:43 +01:00
307e1f9356 Implement e2e tests 2018-05-29 22:39:15 +01:00
11 changed files with 6308 additions and 4813 deletions

20
Dockerfile Normal file
View File

@ -0,0 +1,20 @@
FROM selenium/node-chrome:latest
USER root
RUN apt-get update -qqy \
&& apt-get -qqy install python git build-essential \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
&& rm /bin/sh && ln -s /bin/bash /bin/sh \
&& chown seluser /usr/local
ENV NVM_DIR /usr/local/nvm
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install v8
ENV CHROME_BIN /opt/google/chrome/chrome
ENV INSIDE_DOCKER=1
WORKDIR /usr/src
ENTRYPOINT source $NVM_DIR/nvm.sh && npm i && npm test

View File

@ -21,8 +21,8 @@
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"dev": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.3.5"
"delegates": "^1.0.0",
"readable-stream": "^2.0.6"
}
},
"balanced-match": {
@ -43,7 +43,7 @@
"integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=",
"dev": true,
"requires": {
"readable-stream": "2.3.5"
"readable-stream": "^2.0.5"
}
},
"block-stream": {
@ -52,7 +52,7 @@
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"dev": true,
"requires": {
"inherits": "2.0.3"
"inherits": "~2.0.0"
}
},
"brace-expansion": {
@ -61,7 +61,7 @@
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "1.0.0",
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
@ -72,8 +72,8 @@
"dev": true,
"requires": {
"base64-js": "0.0.8",
"ieee754": "1.1.8",
"isarray": "1.0.0"
"ieee754": "^1.1.4",
"isarray": "^1.0.0"
}
},
"buffer-crc32": {
@ -88,10 +88,10 @@
"integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
"dev": true,
"requires": {
"get-proxy": "2.1.0",
"isurl": "1.0.0",
"tunnel-agent": "0.6.0",
"url-to-options": "1.0.1"
"get-proxy": "^2.0.0",
"isurl": "^1.0.0-alpha5",
"tunnel-agent": "^0.6.0",
"url-to-options": "^1.0.1"
}
},
"code-point-at": {
@ -106,7 +106,7 @@
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
"dev": true,
"requires": {
"graceful-readlink": "1.0.1"
"graceful-readlink": ">= 1.0.0"
}
},
"concat-map": {
@ -121,8 +121,8 @@
"integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=",
"dev": true,
"requires": {
"ini": "1.3.5",
"proto-list": "1.2.4"
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"console-control-strings": {
@ -158,14 +158,14 @@
"integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
"dev": true,
"requires": {
"decompress-tar": "4.1.1",
"decompress-tarbz2": "4.1.1",
"decompress-targz": "4.1.1",
"decompress-unzip": "4.0.1",
"graceful-fs": "4.1.11",
"make-dir": "1.2.0",
"pify": "2.3.0",
"strip-dirs": "2.1.0"
"decompress-tar": "^4.0.0",
"decompress-tarbz2": "^4.0.0",
"decompress-targz": "^4.0.0",
"decompress-unzip": "^4.0.1",
"graceful-fs": "^4.1.10",
"make-dir": "^1.0.0",
"pify": "^2.3.0",
"strip-dirs": "^2.0.0"
},
"dependencies": {
"pify": {
@ -182,7 +182,7 @@
"integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=",
"dev": true,
"requires": {
"mimic-response": "1.0.0"
"mimic-response": "^1.0.0"
}
},
"decompress-tar": {
@ -191,9 +191,9 @@
"integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
"dev": true,
"requires": {
"file-type": "5.2.0",
"is-stream": "1.1.0",
"tar-stream": "1.5.5"
"file-type": "^5.2.0",
"is-stream": "^1.1.0",
"tar-stream": "^1.5.2"
}
},
"decompress-tarbz2": {
@ -202,11 +202,11 @@
"integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
"dev": true,
"requires": {
"decompress-tar": "4.1.1",
"file-type": "6.2.0",
"is-stream": "1.1.0",
"seek-bzip": "1.0.5",
"unbzip2-stream": "1.2.5"
"decompress-tar": "^4.1.0",
"file-type": "^6.1.0",
"is-stream": "^1.1.0",
"seek-bzip": "^1.0.5",
"unbzip2-stream": "^1.0.9"
},
"dependencies": {
"file-type": {
@ -223,9 +223,9 @@
"integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
"dev": true,
"requires": {
"decompress-tar": "4.1.1",
"file-type": "5.2.0",
"is-stream": "1.1.0"
"decompress-tar": "^4.1.1",
"file-type": "^5.2.0",
"is-stream": "^1.1.0"
}
},
"decompress-unzip": {
@ -234,10 +234,10 @@
"integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
"dev": true,
"requires": {
"file-type": "3.9.0",
"get-stream": "2.3.1",
"pify": "2.3.0",
"yauzl": "2.9.1"
"file-type": "^3.8.0",
"get-stream": "^2.2.0",
"pify": "^2.3.0",
"yauzl": "^2.4.2"
},
"dependencies": {
"file-type": {
@ -252,8 +252,8 @@
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
"dev": true,
"requires": {
"object-assign": "4.1.1",
"pinkie-promise": "2.0.1"
"object-assign": "^4.0.1",
"pinkie-promise": "^2.0.0"
}
},
"pify": {
@ -282,17 +282,17 @@
"integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==",
"dev": true,
"requires": {
"caw": "2.0.1",
"content-disposition": "0.5.2",
"decompress": "4.2.0",
"ext-name": "5.0.0",
"caw": "^2.0.0",
"content-disposition": "^0.5.2",
"decompress": "^4.0.0",
"ext-name": "^5.0.0",
"file-type": "5.2.0",
"filenamify": "2.0.0",
"get-stream": "3.0.0",
"got": "7.1.0",
"make-dir": "1.2.0",
"p-event": "1.3.0",
"pify": "3.0.0"
"filenamify": "^2.0.0",
"get-stream": "^3.0.0",
"got": "^7.0.0",
"make-dir": "^1.0.0",
"p-event": "^1.0.0",
"pify": "^3.0.0"
}
},
"duplexer3": {
@ -307,7 +307,7 @@
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "1.4.0"
"once": "^1.4.0"
}
},
"error-ex": {
@ -316,7 +316,7 @@
"integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
"dev": true,
"requires": {
"is-arrayish": "0.2.1"
"is-arrayish": "^0.2.1"
}
},
"escape-string-regexp": {
@ -331,7 +331,7 @@
"integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
"dev": true,
"requires": {
"mime-db": "1.33.0"
"mime-db": "^1.28.0"
}
},
"ext-name": {
@ -340,8 +340,8 @@
"integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
"dev": true,
"requires": {
"ext-list": "2.2.2",
"sort-keys-length": "1.0.1"
"ext-list": "^2.0.0",
"sort-keys-length": "^1.0.0"
}
},
"extend": {
@ -356,7 +356,7 @@
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
"dev": true,
"requires": {
"pend": "1.2.0"
"pend": "~1.2.0"
}
},
"file-type": {
@ -377,9 +377,9 @@
"integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=",
"dev": true,
"requires": {
"filename-reserved-regex": "2.0.0",
"strip-outer": "1.0.0",
"trim-repeated": "1.0.0"
"filename-reserved-regex": "^2.0.0",
"strip-outer": "^1.0.0",
"trim-repeated": "^1.0.0"
}
},
"fs.realpath": {
@ -394,10 +394,10 @@
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"inherits": "2.0.3",
"mkdirp": "0.5.1",
"rimraf": "2.6.2"
"graceful-fs": "^4.1.2",
"inherits": "~2.0.0",
"mkdirp": ">=0.5 0",
"rimraf": "2"
}
},
"fstream-ignore": {
@ -406,9 +406,9 @@
"integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
"dev": true,
"requires": {
"fstream": "1.0.11",
"inherits": "2.0.3",
"minimatch": "3.0.4"
"fstream": "^1.0.0",
"inherits": "2",
"minimatch": "^3.0.0"
}
},
"gauge": {
@ -417,14 +417,14 @@
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"dev": true,
"requires": {
"aproba": "1.2.0",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.0",
"object-assign": "^4.1.0",
"signal-exit": "^3.0.0",
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wide-align": "^1.1.0"
}
},
"get-proxy": {
@ -433,7 +433,7 @@
"integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
"dev": true,
"requires": {
"npm-conf": "1.1.3"
"npm-conf": "^1.1.0"
}
},
"get-stream": {
@ -448,12 +448,12 @@
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"got": {
@ -462,20 +462,20 @@
"integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
"dev": true,
"requires": {
"decompress-response": "3.3.0",
"duplexer3": "0.1.4",
"get-stream": "3.0.0",
"is-plain-obj": "1.1.0",
"is-retry-allowed": "1.1.0",
"is-stream": "1.1.0",
"isurl": "1.0.0",
"lowercase-keys": "1.0.0",
"p-cancelable": "0.3.0",
"p-timeout": "1.2.1",
"safe-buffer": "5.1.1",
"timed-out": "4.0.1",
"url-parse-lax": "1.0.0",
"url-to-options": "1.0.1"
"decompress-response": "^3.2.0",
"duplexer3": "^0.1.4",
"get-stream": "^3.0.0",
"is-plain-obj": "^1.1.0",
"is-retry-allowed": "^1.0.0",
"is-stream": "^1.0.0",
"isurl": "^1.0.0-alpha5",
"lowercase-keys": "^1.0.0",
"p-cancelable": "^0.3.0",
"p-timeout": "^1.1.1",
"safe-buffer": "^5.0.1",
"timed-out": "^4.0.0",
"url-parse-lax": "^1.0.0",
"url-to-options": "^1.0.1"
}
},
"graceful-fs": {
@ -502,7 +502,7 @@
"integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
"dev": true,
"requires": {
"has-symbol-support-x": "1.4.2"
"has-symbol-support-x": "^1.4.1"
}
},
"has-unicode": {
@ -529,8 +529,8 @@
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
@ -557,7 +557,7 @@
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "1.0.1"
"number-is-nan": "^1.0.0"
}
},
"is-natural-number": {
@ -602,8 +602,8 @@
"integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
"dev": true,
"requires": {
"has-to-string-tag-x": "1.4.1",
"is-object": "1.0.1"
"has-to-string-tag-x": "^1.2.0",
"is-object": "^1.0.1"
}
},
"load-json-file": {
@ -612,10 +612,10 @@
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"parse-json": "2.2.0",
"pify": "2.3.0",
"strip-bom": "3.0.0"
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
"pify": "^2.0.0",
"strip-bom": "^3.0.0"
},
"dependencies": {
"pify": {
@ -638,7 +638,7 @@
"integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==",
"dev": true,
"requires": {
"pify": "3.0.0"
"pify": "^3.0.0"
}
},
"mime-db": {
@ -659,7 +659,7 @@
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "1.1.11"
"brace-expansion": "^1.1.7"
}
},
"minimist": {
@ -697,16 +697,16 @@
"integrity": "sha1-7DqP3gcZC2ny/kNMOVo+aUaEG1Y=",
"dev": true,
"requires": {
"download": "6.2.5",
"extend": "3.0.1",
"load-json-file": "2.0.0",
"minimist": "1.2.0",
"mkdirp": "0.5.1",
"npm-cache-filename": "1.0.2",
"npmlog": "4.1.2",
"rimraf": "2.6.2",
"tar-pack": "3.4.1",
"write-json-file": "2.3.0"
"download": "^6.2.2",
"extend": "^3.0.1",
"load-json-file": "^2.0.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"npm-cache-filename": "^1.0.2",
"npmlog": "^4.1.0",
"rimraf": "^2.6.1",
"tar-pack": "^3.4.0",
"write-json-file": "^2.2.0"
}
},
"npm-cache-filename": {
@ -721,8 +721,8 @@
"integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
"dev": true,
"requires": {
"config-chain": "1.1.11",
"pify": "3.0.0"
"config-chain": "^1.1.11",
"pify": "^3.0.0"
}
},
"npmlog": {
@ -731,10 +731,10 @@
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"dev": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
"are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0",
"gauge": "~2.7.3",
"set-blocking": "~2.0.0"
}
},
"number-is-nan": {
@ -755,7 +755,7 @@
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1.0.2"
"wrappy": "1"
}
},
"p-cancelable": {
@ -770,7 +770,7 @@
"integrity": "sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=",
"dev": true,
"requires": {
"p-timeout": "1.2.1"
"p-timeout": "^1.1.1"
}
},
"p-finally": {
@ -785,7 +785,7 @@
"integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=",
"dev": true,
"requires": {
"p-finally": "1.0.0"
"p-finally": "^1.0.0"
}
},
"parse-json": {
@ -794,7 +794,7 @@
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"dev": true,
"requires": {
"error-ex": "1.3.1"
"error-ex": "^1.2.0"
}
},
"path-is-absolute": {
@ -827,7 +827,7 @@
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
"dev": true,
"requires": {
"pinkie": "2.0.4"
"pinkie": "^2.0.0"
}
},
"prepend-http": {
@ -854,13 +854,13 @@
"integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==",
"dev": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "2.0.0",
"safe-buffer": "5.1.1",
"string_decoder": "1.0.3",
"util-deprecate": "1.0.2"
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.0.3",
"util-deprecate": "~1.0.1"
}
},
"rimraf": {
@ -869,7 +869,7 @@
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"dev": true,
"requires": {
"glob": "7.1.2"
"glob": "^7.0.5"
}
},
"safe-buffer": {
@ -884,7 +884,7 @@
"integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
"dev": true,
"requires": {
"commander": "2.8.1"
"commander": "~2.8.1"
}
},
"set-blocking": {
@ -905,7 +905,7 @@
"integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
"dev": true,
"requires": {
"is-plain-obj": "1.1.0"
"is-plain-obj": "^1.0.0"
}
},
"sort-keys-length": {
@ -914,7 +914,7 @@
"integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=",
"dev": true,
"requires": {
"sort-keys": "1.1.2"
"sort-keys": "^1.0.0"
}
},
"string-width": {
@ -923,9 +923,9 @@
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"string_decoder": {
@ -934,7 +934,7 @@
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
"safe-buffer": "~5.1.0"
}
},
"strip-ansi": {
@ -943,7 +943,7 @@
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "2.1.1"
"ansi-regex": "^2.0.0"
}
},
"strip-bom": {
@ -958,7 +958,7 @@
"integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
"dev": true,
"requires": {
"is-natural-number": "4.0.1"
"is-natural-number": "^4.0.1"
}
},
"strip-outer": {
@ -967,7 +967,7 @@
"integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=",
"dev": true,
"requires": {
"escape-string-regexp": "1.0.5"
"escape-string-regexp": "^1.0.2"
}
},
"tar": {
@ -976,9 +976,9 @@
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
"dev": true,
"requires": {
"block-stream": "0.0.9",
"fstream": "1.0.11",
"inherits": "2.0.3"
"block-stream": "*",
"fstream": "^1.0.2",
"inherits": "2"
}
},
"tar-pack": {
@ -987,14 +987,14 @@
"integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==",
"dev": true,
"requires": {
"debug": "2.6.9",
"fstream": "1.0.11",
"fstream-ignore": "1.0.5",
"once": "1.4.0",
"readable-stream": "2.3.5",
"rimraf": "2.6.2",
"tar": "2.2.1",
"uid-number": "0.0.6"
"debug": "^2.2.0",
"fstream": "^1.0.10",
"fstream-ignore": "^1.0.5",
"once": "^1.3.3",
"readable-stream": "^2.1.4",
"rimraf": "^2.5.1",
"tar": "^2.2.1",
"uid-number": "^0.0.6"
}
},
"tar-stream": {
@ -1003,10 +1003,10 @@
"integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==",
"dev": true,
"requires": {
"bl": "1.2.1",
"end-of-stream": "1.4.1",
"readable-stream": "2.3.5",
"xtend": "4.0.1"
"bl": "^1.0.0",
"end-of-stream": "^1.0.0",
"readable-stream": "^2.0.0",
"xtend": "^4.0.0"
}
},
"through": {
@ -1027,7 +1027,7 @@
"integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
"dev": true,
"requires": {
"escape-string-regexp": "1.0.5"
"escape-string-regexp": "^1.0.2"
}
},
"tunnel-agent": {
@ -1036,7 +1036,7 @@
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
"safe-buffer": "^5.0.1"
}
},
"uid-number": {
@ -1051,8 +1051,8 @@
"integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
"dev": true,
"requires": {
"buffer": "3.6.0",
"through": "2.3.8"
"buffer": "^3.0.1",
"through": "^2.3.6"
}
},
"url-parse-lax": {
@ -1061,7 +1061,7 @@
"integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
"dev": true,
"requires": {
"prepend-http": "1.0.4"
"prepend-http": "^1.0.1"
}
},
"url-to-options": {
@ -1082,7 +1082,7 @@
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"dev": true,
"requires": {
"string-width": "1.0.2"
"string-width": "^1.0.2"
}
},
"wrappy": {
@ -1097,9 +1097,9 @@
"integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
"dev": true,
"requires": {
"graceful-fs": "4.1.11",
"imurmurhash": "0.1.4",
"signal-exit": "3.0.2"
"graceful-fs": "^4.1.11",
"imurmurhash": "^0.1.4",
"signal-exit": "^3.0.2"
}
},
"write-json-file": {
@ -1108,12 +1108,12 @@
"integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=",
"dev": true,
"requires": {
"detect-indent": "5.0.0",
"graceful-fs": "4.1.11",
"make-dir": "1.2.0",
"pify": "3.0.0",
"sort-keys": "2.0.0",
"write-file-atomic": "2.3.0"
"detect-indent": "^5.0.0",
"graceful-fs": "^4.1.2",
"make-dir": "^1.0.0",
"pify": "^3.0.0",
"sort-keys": "^2.0.0",
"write-file-atomic": "^2.0.0"
},
"dependencies": {
"sort-keys": {
@ -1122,7 +1122,7 @@
"integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=",
"dev": true,
"requires": {
"is-plain-obj": "1.1.0"
"is-plain-obj": "^1.0.0"
}
}
}
@ -1139,8 +1139,8 @@
"integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=",
"dev": true,
"requires": {
"buffer-crc32": "0.2.13",
"fd-slicer": "1.0.1"
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.0.1"
}
}
}

113
karma.conf.js Normal file
View File

@ -0,0 +1,113 @@
const fs = require("fs");
function readJsonFile(path) {
// TypeScript puts lots of comments in the default `tsconfig.json`, so you
// cant use `require()` to read it. Hence this hack.
return eval("(" + fs.readFileSync(path).toString("utf-8") + ")");
}
const typeScriptConfig = readJsonFile("./tsconfig.json");
const babel = readJsonFile("./.babelrc");
module.exports = function(config) {
const options = {
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: "",
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ["mocha", "chai", "karma-typescript"],
// list of files / patterns to load in the browser
files: [
{
pattern: "test/**/*.ts",
type: "module"
},
{
pattern: "src/**/*.ts",
included: false
}
],
// list of files / patterns to exclude
exclude: [],
// preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
"src/**/*.ts": ["karma-typescript", "babel"],
"test/**/*.ts": ["karma-typescript", "babel"]
},
babelPreprocessor: {
options: babel
},
karmaTypescriptConfig: {
// Inline `tsconfig.json` so that the right TS libs are loaded
...typeScriptConfig,
// Coverage is a thing that karma-typescript forces on you and only
// creates problems. This is the simplest way of disabling it that I
// could find.
coverageOptions: {
exclude: /.*/
}
},
mime: {
// Default mimetype for .ts files is video/mp2t but we need
// text/javascript for modules to work.
"text/javascript": ["ts"]
},
plugins: [
// Load all modules whose name starts with "karma" (usually the default).
"karma-*",
// We dont have file extensions on our imports as they are primarily
// consumed by webpack. With Karma, however, this turns into a real HTTP
// request for a non-existent file. This inline plugin is a middleware
// that appends `.ts` to the request URL.
{
"middleware:redirect_to_ts": [
"value",
(req, res, next) => {
if (req.url.startsWith("/base/src")) {
req.url += '.ts';
}
next();
}
]
}
],
// Run our middleware before all other middlewares.
beforeMiddleware: ["redirect_to_ts"],
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ["progress"],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ["ChromeHeadless"],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// These custom files allow us to use ES6 modules in our tests.
// Remove these 2 lines (and files) once https://github.com/karma-runner/karma/pull/2834 lands.
customContextFile: "test/context.html",
customDebugFile: "test/debug.html"
};
config.set(options);
};

10387
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,8 @@
"build:codecs": "npm run build:mozjpeg_enc",
"start": "webpack serve --host 0.0.0.0 --hot",
"build": "webpack -p",
"lint": "eslint src"
"lint": "eslint src",
"test": "npm run build && mocha -R spec && karma start"
},
"eslintConfig": {
"extends": [
@ -31,6 +32,9 @@
"build/*"
],
"devDependencies": {
"@types/chai": "^4.1.3",
"@types/karma": "^1.7.3",
"@types/mocha": "^5.2.0",
"@types/node": "^9.4.7",
"@types/webassembly-js-api": "0.0.1",
"babel-loader": "^7.1.4",
@ -44,6 +48,7 @@
"babel-plugin-transform-react-remove-prop-types": "^0.4.13",
"babel-preset-env": "^1.6.1",
"babel-register": "^6.26.0",
"chai": "^4.1.2",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^4.5.1",
"css-loader": "^0.28.11",
@ -56,14 +61,24 @@
"eslint-plugin-react": "^7.7.0",
"eslint-plugin-standard": "^3.0.1",
"exports-loader": "^0.7.0",
"express": "^4.16.3",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.0.6",
"if-env": "^1.0.4",
"karma": "^2.0.2",
"karma-babel-preprocessor": "^7.0.0",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"karma-typescript": "^3.0.12",
"loader-utils": "^1.1.0",
"mini-css-extract-plugin": "^0.3.0",
"mocha": "^5.2.0",
"node-sass": "^4.7.2",
"optimize-css-assets-webpack-plugin": "^4.0.0",
"prettier": "^1.12.1",
"progress-bar-webpack-plugin": "^1.11.0",
"puppeteer": "^1.3.0",
"raw-loader": "^0.5.1",
"sass-loader": "^6.0.7",
"script-ext-html-webpack-plugin": "^2.0.1",

41
test/context.html Normal file
View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<!--
This file is taken from https://github.com/karma-runner/karma/pull/2834. It allows us to use ES6 module imports in our test suite files.
-->
<!--
This is the execution context.
Loaded within the iframe.
Reloaded before every execution run.
-->
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head>
<body>
<!-- The scripts need to be in the body DOM element, as some test running frameworks need the body
to have already been created so they can insert their magic into it. For example, if loaded
before body, Angular Scenario test framework fails to find the body and crashes and burns in
an epic manner. -->
<script src="context.js"></script>
<script type="text/javascript">
// Configure our Karma and set up bindings
%CLIENT_CONFIG%
window.__karma__.setupContext(window);
// All served files with the latest timestamps
%MAPPINGS%
</script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<!-- Since %SCRIPTS% might include modules, the `loaded()` call needs to be in a module too.
This ensures all the tests will have been declared before karma tries to run them. -->
<script type="module">
window.__karma__.loaded();
</script>
<script nomodule>
window.__karma__.loaded();
</script>
</body>
</html>

43
test/debug.html Normal file
View File

@ -0,0 +1,43 @@
<!doctype html>
<!--
This file is taken from https://github.com/karma-runner/karma/pull/2834. It allows us to use ES6 module imports in our test suite files.
-->
<!--
This file is almost the same as context.html - loads all source files,
but its purpose is to be loaded in the main frame (not within an iframe),
just for immediate execution, without reporting to Karma server.
-->
<html>
<head>
%X_UA_COMPATIBLE%
<title>Karma DEBUG RUNNER</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head>
<body>
<!-- The scripts need to be at the end of body, so that some test running frameworks
(Angular Scenario, for example) need the body to be loaded so that it can insert its magic
into it. If it is before body, then it fails to find the body and crashes and burns in an epic
manner. -->
<script src="context.js"></script>
<script src="debug.js"></script>
<script type="text/javascript">
// Configure our Karma
%CLIENT_CONFIG%
// All served files with the latest timestamps
%MAPPINGS%
</script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<!-- Since %SCRIPTS% might include modules, the `loaded()` call needs to be in a module too.
This ensures all the tests will have been declared before karma tries to run them. -->
<script type="module">
window.__karma__.loaded();
</script>
<script nomodule>
window.__karma__.loaded();
</script>
</body>
</html>

66
test/e2etest.js Normal file
View File

@ -0,0 +1,66 @@
const express = require("express");
const app = express();
const http = require("http");
const puppeteer = require("puppeteer");
const { fingerDown } = require("./finger.js");
const { expect } = require("chai");
async function staticWebServer(path) {
// Start a static web server
const app = express();
app.use(express.static(path));
// Port 0 means let the OS select a port
const server = http.createServer(app).listen(0, "localhost");
await new Promise(resolve => server.on("listening", resolve));
// Read back the bound address
const address = server.address();
return { server, address };
}
describe("some e2e test", function() {
before(async function() {
// Start webserver
const { address, server } = await staticWebServer(".");
this.address = `http://${address.address}:${address.port}`;
this.server = server;
// Start browser
this.browser = await puppeteer.launch();
this.page = await this.browser.newPage();
await this.page.goto(`${this.address}/test/sample.html`, {
waitUntil: "networkidle2"
});
});
it("can tap", async function() {
const btn = await this.page.$("button");
await btn.tap();
const result = await this.page.evaluate(_ => {
return window.lol;
});
expect(result).to.equal(true);
});
it("can tap manually", async function() {
const btn = await this.page.$("button");
const box = await btn.boundingBox();
const finger = fingerDown(
this.page,
box.x + box.width / 2,
box.y + box.height / 2
);
finger.up();
const result = await this.page.evaluate(_ => {
return window.lol;
});
expect(result).to.equal(true);
});
it("does some taps", async function() {});
after(async function() {
this.server.close();
await this.browser.close();
});
});

61
test/finger.js Normal file
View File

@ -0,0 +1,61 @@
let touchPoints = [];
let idCnt = 0;
class Finger {
constructor(point, page) {
this._point = point;
this._page = page;
}
move(x, y) {
if (!this._point) return;
Object.assign(this._point, {
x: Math.floor(x),
y: Math.floor(y)
});
this._page.touchscreen._client.send("Input.dispatchTouchEvent", {
type: "touchMove",
touchPoints,
modifiers: page._keyboard._modifiers
});
}
up() {
if (!this._point) return;
const idx = touchPoints.indexOf(this._point);
touchPoints = touchPoints.splice(idx, 1);
this._point = null;
if (touchPoints.length === 0) {
this._page.touchscreen._client.send("Input.dispatchTouchEvent", {
type: "touchEnd",
modifiers: this._page._keyboard._modifiers
});
} else {
this._page.touchscreen._client.send("Input.dispatchTouchEvent", {
type: "touchMove",
touchPoints,
modifiers: this._page._keyboard._modifiers
});
}
}
}
function fingerDown(page, x, y) {
const id = idCnt++;
const point = {
x: Math.round(x),
y: Math.round(y),
id
};
touchPoints.push(point);
page.touchscreen._client.send("Input.dispatchTouchEvent", {
type: "touchStart",
touchPoints,
modifiers: page._keyboard._modifiers
});
return new Finger(point, page);
}
module.exports = {
fingerDown
};

9
test/lib/util.ts Normal file
View File

@ -0,0 +1,9 @@
import {bitmapToImageData} from "../../src/lib/util";
const expect = chai.expect;
describe("util.bitmapToImageData", function () {
it("is a function", function () {
expect(bitmapToImageData).to.be.a('function');
});
});

6
test/sample.html Normal file
View File

@ -0,0 +1,6 @@
<!doctype html>
<button>Test me</button>
<script>
document.querySelector('button').onclick = _ => window.lol = true;
</script>