From 2457a2b2d91d080a18ec10720fd6531cd6db3b08 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Sat, 3 Oct 2015 21:54:08 -0400 Subject: [PATCH] (#4402) - fix Firefox FileReader in a WW This also re-enables the web worker tests for Firefox. Web worker tests should only be running in Chrome and Firefox now. --- .jshintrc | 3 +- .travis.yml | 23 +++-- bin/test-browser.js | 2 +- lib/deps/binary/readAsArrayBuffer.js | 6 ++ lib/deps/binary/readAsBinaryString.js | 7 ++ tests/integration/browser.worker.js | 120 ++++++++++++-------------- tests/integration/worker.js | 103 +++++++++++----------- 7 files changed, 134 insertions(+), 130 deletions(-) diff --git a/.jshintrc b/.jshintrc index 13c30f08cf..2a33813a3c 100755 --- a/.jshintrc +++ b/.jshintrc @@ -38,6 +38,7 @@ "IDBKeyRange", "openDatabase", "sqlitePlugin", - "chrome" + "chrome", + "FileReaderSync" ] } diff --git a/.travis.yml b/.travis.yml index ae6de8a2aa..c1b13b4cc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ git: # - /tmp/phantomjs addons: + firefox: "41.0.1" apt: sources: - ubuntu-toolchain-r-test @@ -58,29 +59,27 @@ env: # Test against pouchdb-server - CLIENT=node SERVER=pouchdb-server COMMAND=test - - CLIENT=selenium:firefox SERVER=pouchdb-server COMMAND=test + - CLIENT=selenium:firefox:41.0.1 SERVER=pouchdb-server COMMAND=test - SERVER_ADAPTER=memdown LEVEL_ADAPTER=memdown SERVER=pouchdb-server COMMAND=test # Test against pouchdb-express-router - CLIENT=node SERVER=pouchdb-express-router COMMAND=test # Test in firefox/phantomjs running on travis - - CLIENT=selenium:firefox COMMAND=test + - CLIENT=selenium:firefox:41.0.1 COMMAND=test - CLIENT=selenium:phantomjs ES5_SHIM=true COMMAND=test # Test auto-compaction in Node, Phantom, and Firefox - AUTO_COMPACTION=true CLIENT=node COMMAND=test - - AUTO_COMPACTION=true CLIENT=selenium:firefox COMMAND=test + - AUTO_COMPACTION=true CLIENT=selenium:firefox:41.0.1 COMMAND=test - AUTO_COMPACTION=true CLIENT=selenium:phantomjs ES5_SHIM=true COMMAND=test # Test map/reduce - TYPE=mapreduce CLIENT=node COMMAND=test - - TYPE=mapreduce CLIENT=selenium:firefox COMMAND=test + - TYPE=mapreduce CLIENT=selenium:firefox:41.0.1 COMMAND=test - TYPE=mapreduce CLIENT=selenium:phantomjs ES5_SHIM=true COMMAND=test # Testing in saucelabs - - CLIENT=saucelabs:chrome:36 COMMAND=test - - CLIENT=saucelabs:chrome:37 COMMAND=test - CLIENT=saucelabs:chrome COMMAND=test - CLIENT=saucelabs:safari:6 COMMAND=test - CLIENT="saucelabs:internet explorer:10:Windows 8" COMMAND=test @@ -93,18 +92,18 @@ env: - GREP=suite2 CLIENT="saucelabs:Android:5.1:Linux" COMMAND=test - GREP=suite2 INVERT=true CLIENT="saucelabs:Android:5.1:Linux" COMMAND=test - - CLIENT=selenium:firefox ADAPTERS=memory COMMAND=test - - CLIENT=selenium:firefox ADAPTERS=localstorage COMMAND=test + - CLIENT=selenium:firefox:41.0.1 ADAPTERS=memory COMMAND=test + - CLIENT=selenium:firefox:41.0.1 ADAPTERS=localstorage COMMAND=test # Test CouchDB master (aka bigcouch branch) - CLIENT=node SERVER=couchdb-master COMMAND=test - - SKIP_MIGRATION=true CLIENT=selenium:firefox SERVER=couchdb-master COMMAND=test + - SKIP_MIGRATION=true CLIENT=selenium:firefox:41.0.1 SERVER=couchdb-master COMMAND=test # Test Couchbase Sync Gateway - GREP=test.replication.js CLIENT=node SERVER=sync-gateway BAIL=0 COMMAND=test # Performance tests - - CLIENT=selenium:firefox PERF=1 COMMAND=test + - CLIENT=selenium:firefox:41.0.1 PERF=1 COMMAND=test - PERF=1 COMMAND=test - COMMAND=test-unit @@ -121,12 +120,12 @@ matrix: # Allowed failures - env: CLIENT=node SERVER=couchdb-master COMMAND=test - - env: SKIP_MIGRATION=true CLIENT=selenium:firefox SERVER=couchdb-master COMMAND=test + - env: SKIP_MIGRATION=true CLIENT=selenium:firefox:41.0.1 SERVER=couchdb-master COMMAND=test - env: CLIENT=node SERVER=pouchdb-express-router COMMAND=test - node_js: "iojs" env: CLIENT=node COMMAND=test - env: CLIENT=node SERVER=pouchdb-server COMMAND=test - - env: CLIENT=selenium:firefox SERVER=pouchdb-server COMMAND=test + - env: CLIENT=selenium:firefox:41.0.1 SERVER=pouchdb-server COMMAND=test - env: SERVER_ADAPTER=memdown LEVEL_ADAPTER=memdown SERVER=pouchdb-server COMMAND=test - env: COMMAND=report-coverage diff --git a/bin/test-browser.js b/bin/test-browser.js index 9304645875..1d45edf155 100755 --- a/bin/test-browser.js +++ b/bin/test-browser.js @@ -16,7 +16,7 @@ var testTimeout = 30 * 60 * 1000; var username = process.env.SAUCE_USERNAME; var accessKey = process.env.SAUCE_ACCESS_KEY; -var SELENIUM_VERSION = process.env.SELENIUM_VERSION || '2.46.0'; +var SELENIUM_VERSION = process.env.SELENIUM_VERSION || '2.45.0'; // BAIL=0 to disable bailing var bail = process.env.BAIL !== '0'; diff --git a/lib/deps/binary/readAsArrayBuffer.js b/lib/deps/binary/readAsArrayBuffer.js index c191d13869..224bec1893 100644 --- a/lib/deps/binary/readAsArrayBuffer.js +++ b/lib/deps/binary/readAsArrayBuffer.js @@ -2,6 +2,12 @@ // simplified API. universal browser support is assumed module.exports = function (blob, callback) { + if (typeof FileReader === 'undefined') { + // fix for Firefox in a web worker: + // https://bugzilla.mozilla.org/show_bug.cgi?id=901097 + return callback(new FileReaderSync().readAsArrayBuffer(blob)); + } + var reader = new FileReader(); reader.onloadend = function (e) { var result = e.target.result || new ArrayBuffer(0); diff --git a/lib/deps/binary/readAsBinaryString.js b/lib/deps/binary/readAsBinaryString.js index 466723e913..defe2867aa 100644 --- a/lib/deps/binary/readAsBinaryString.js +++ b/lib/deps/binary/readAsBinaryString.js @@ -4,6 +4,13 @@ var arrayBufferToBinaryString = require('./arrayBufferToBinaryString'); // shim for browsers that don't support it module.exports = function (blob, callback) { + if (typeof FileReader === 'undefined') { + // fix for Firefox in a web worker + // https://bugzilla.mozilla.org/show_bug.cgi?id=901097 + return callback(arrayBufferToBinaryString( + new FileReaderSync().readAsArrayBuffer(blob))); + } + var reader = new FileReader(); var hasBinaryString = typeof reader.readAsBinaryString === 'function'; reader.onloadend = function (e) { diff --git a/tests/integration/browser.worker.js b/tests/integration/browser.worker.js index 38d015defd..5bc5f68212 100644 --- a/tests/integration/browser.worker.js +++ b/tests/integration/browser.worker.js @@ -8,12 +8,38 @@ if (!sourceFile) { sourceFile = '../../dist/' + sourceFile[1]; } -if (typeof window.Worker === 'function' && window.chrome) { +// only running in Chrome and Firefox due to various bugs. +// IE: https://connect.microsoft.com/IE/feedback/details/866495 +// Safari: doesn't have IndexedDB or WebSQL in a WW +// NodeWebkit: not sure what the issue is + +var isNodeWebkit = typeof window !== 'undefined' && + typeof process !== 'undefined'; + +if (typeof window.Worker === 'function' && + !isNodeWebkit && + (window.chrome || /Firefox/.test(navigator.userAgent))) { runTests(); } function runTests() { + function workerPromise(message) { + return new Promise(function (resolve, reject) { + var worker = new Worker('worker.js'); + worker.addEventListener('error', function (e) { + worker.terminate(); + reject(new Error(e.message + ": " + e.filename + ': ' + e.lineno)); + }); + worker.addEventListener('message', function (e) { + worker.terminate(); + resolve(e.data); + }); + worker.postMessage(['source', sourceFile]); + worker.postMessage(message); + }); + } + describe('browser.worker.js', function () { var dbs = {}; @@ -28,82 +54,44 @@ function runTests() { testUtils.cleanup([dbs.name, dbs.remote], done); }); - it('add doc with blob attachemnt', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('error', function (e) { - throw e; + it('create it', function () { + return workerPromise('ping').then(function (data) { + data.should.equal('pong'); }); - worker.addEventListener('message', function (e) { - e.data.title.should.equal('lalaa'); - worker.terminate(); - done(); + }); + + it('check pouch version', function () { + return workerPromise('version').then(function (data) { + PouchDB.version.should.equal(data); }); - worker.postMessage(sourceFile); - worker.postMessage(['allDocs', 'testdb']); }); - it('create it', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('message', function (e) { - e.data.should.equal('pong'); - worker.terminate(); - done(); + it('create remote db', function () { + return workerPromise(['create', dbs.remote]).then(function (data) { + data.should.equal('lala'); }); - worker.postMessage(sourceFile); - worker.postMessage('ping'); }); - it('check pouch version', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('message', function (e) { - PouchDB.version.should.equal(e.data); - worker.terminate(); - done(); + it('create local db', function () { + return workerPromise(['create', dbs.name]).then(function (data) { + data.should.equal('lala'); }); - worker.postMessage(sourceFile); - worker.postMessage('version'); }); - var isNodeWebkit = typeof window !== 'undefined' && - typeof process !== 'undefined'; - - // does not work in NodeWebkit - if (!isNodeWebkit) { - it('create remote db', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('error', function (e) { - throw e; - }); - worker.addEventListener('message', function (e) { - e.data.should.equal('lala'); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage(['create', dbs.remote]); + it('add doc with blob attachment', function () { + return workerPromise(['allDocs', dbs.name]).then(function (data) { + data.title.should.equal('lalaa'); }); - } - - - // Mozilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=701634 - // IE bug: https://connect.microsoft.com/IE/feedback/details/866495 - // NodeWebkit bug... who knows - if (!('mozIndexedDB' in window) && - !('msIndexedDB' in window) && - !isNodeWebkit) { - it('create local db', function (done) { - var worker = new Worker('worker.js'); - worker.addEventListener('error', function (e) { - throw e; - }); - worker.addEventListener('message', function (e) { - e.data.should.equal('lala'); - worker.terminate(); - done(); - }); - worker.postMessage(sourceFile); - worker.postMessage(['create', dbs.name]); + }); + + it('put an attachment', function () { + var blob = new Blob(['foobar'], {type: 'text/plain'}); + var message = ['putAttachment', dbs.name, 'doc', 'att.txt', blob, + 'text/plain']; + return workerPromise(message).then(function (blob) { + blob.type.should.equal('text/plain'); + blob.size.should.equal(6); }); - } + }); }); } diff --git a/tests/integration/worker.js b/tests/integration/worker.js index 4c9a2eb8fa..149176c215 100644 --- a/tests/integration/worker.js +++ b/tests/integration/worker.js @@ -1,69 +1,72 @@ /* jshint worker: true */ 'use strict'; +function onError(err) { + setTimeout(function () { + throw err; // can catch this in the worker's 'error' listener + }, 0); +} + function bigTest(name) { - new PouchDB(name, function (err, db) { - if (err) { - throw err; - } - db.post({ - _id: 'blablah', - key: 'lala' - }, function (err) { - if (err) { - throw err; - } - db.get('blablah', function (err, doc) { - if (err) { - throw err; - } - self.postMessage(doc.key); - db.destroy(); - }); + var db = new PouchDB(name); + db.post({ + _id: 'blablah', + key: 'lala' + }).then(function () { + return db.get('blablah'); + }).then(function (doc) { + return db.destroy().then(function () { + self.postMessage(doc.key); }); - }); + }).catch(onError); } function allDocs(name) { - new PouchDB(name, function (err, db) { - if (err) { - throw err; - } - db.post({ - _id: 'blah', - title: 'lalaa', - _attachments: { - 'test': { - data: new Blob(), - content_type: '' - } + var db = new PouchDB(name); + db.post({ + _id: 'blah', + title: 'lalaa', + _attachments: { + 'test': { + data: new Blob(), + content_type: '' } - }, function(err, doc) { - db.get(doc.id, function (err, doc) { - if (err) { - throw err; - } - self.postMessage(doc); - db.destroy(); - }); + } + }).then(function () { + return db.get('blah'); + }).then(function (doc) { + return db.destroy().then(function () { + self.postMessage(doc); + }); + }).catch(onError); +} + +function putAttachment(name, docId, attId, att, type) { + var db = new PouchDB(name); + db.putAttachment(docId, attId, att, type).then(function () { + return db.getAttachment(docId, attId); + }).then(function (fetchedAtt) { + return db.destroy().then(function () { + self.postMessage(fetchedAtt); }); - }); + }).catch(onError); } self.addEventListener('message', function (e) { - if (typeof e.data === 'string' && e.data.indexOf('/dist/') > -1) { - importScripts(e.data); - } - if (e.data === 'ping') { + if (Array.isArray(e.data) && e.data[0] === 'source') { + importScripts(e.data[1]); + } else if (e.data === 'ping') { self.postMessage('pong'); - } - if (e.data === 'version') { + } else if (e.data === 'version') { self.postMessage(PouchDB.version); - } - if (Array.isArray(e.data) && e.data[0] === 'create') { + } else if (Array.isArray(e.data) && e.data[0] === 'create') { bigTest(e.data[1]); - } - if (Array.isArray(e.data) && e.data[0] === 'allDocs') { + } else if (Array.isArray(e.data) && e.data[0] === 'allDocs') { allDocs(e.data[1]); + } else if (Array.isArray(e.data) && e.data[0] === 'putAttachment') { + putAttachment(e.data[1], e.data[2], e.data[3], e.data[4], e.data[5]); + } else { + onError(new Error('unknown message: ' + JSON.stringify(e.data))); } + });