diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..31fa426fa --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +semi: true +trailingComma: "es5" +singleQuote: true +arrowParens: "avoid" +printWidth: 100 \ No newline at end of file diff --git a/integration/cloud/main.js b/integration/cloud/main.js index 6b632de2f..f94f981d8 100644 --- a/integration/cloud/main.js +++ b/integration/cloud/main.js @@ -1,9 +1,9 @@ /* global Parse */ -Parse.Cloud.define("bar", function(request) { - if (request.params.key2 === "value1") { +Parse.Cloud.define('bar', function (request) { + if (request.params.key2 === 'value1') { return 'Foo'; } else { - throw "bad stuff happened"; + throw 'bad stuff happened'; } }); @@ -26,26 +26,26 @@ Parse.Cloud.define('CloudFunctionIdempotency', function () { return object.save(null, { useMasterKey: true }); }); -Parse.Cloud.define('CloudFunctionUndefined', function() { +Parse.Cloud.define('CloudFunctionUndefined', function () { return undefined; }); -Parse.Cloud.job('CloudJob1', function() { +Parse.Cloud.job('CloudJob1', function () { return { - status: 'cloud job completed' + status: 'cloud job completed', }; }); -Parse.Cloud.job('CloudJob2', function() { - return new Promise((resolve) => { - setTimeout(function() { +Parse.Cloud.job('CloudJob2', function () { + return new Promise(resolve => { + setTimeout(function () { resolve({ - status: 'cloud job completed' - }) + status: 'cloud job completed', + }); }, 1000); }); }); -Parse.Cloud.job('CloudJobFailing', function() { +Parse.Cloud.job('CloudJobFailing', function () { throw 'cloud job failed'; }); diff --git a/integration/server.js b/integration/server.js index 35f021190..69af1b260 100644 --- a/integration/server.js +++ b/integration/server.js @@ -20,22 +20,18 @@ const api = new ParseServer({ option2: 'world', }, facebook: { - appIds: "test" + appIds: 'test', }, twitter: { - consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", - consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", + consumer_key: '5QiVwxr8FQHbo5CMw46Z0jquF', + consumer_secret: 'p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK', }, }, verbose: false, silent: true, idempotencyOptions: { - paths: [ - 'functions/CloudFunctionIdempotency', - 'jobs/CloudJob1', - 'classes/IdempotentTest' - ], - ttl: 120 + paths: ['functions/CloudFunctionIdempotency', 'jobs/CloudJob1', 'classes/IdempotentTest'], + ttl: 120, }, serverStartComplete: () => { /* Ignore ParseError: schema class name does not revalidate */ @@ -54,5 +50,5 @@ app.get('/clear/:fast', (req, res) => { }); module.exports = { - app + app, }; diff --git a/integration/test/ArrayOperationsTest.js b/integration/test/ArrayOperationsTest.js index 95cb8a86c..cb9f6f838 100644 --- a/integration/test/ArrayOperationsTest.js +++ b/integration/test/ArrayOperationsTest.js @@ -5,364 +5,437 @@ const clear = require('./clear'); const Parse = require('../../node'); describe('Array Operations', () => { - beforeAll((done) => { + beforeAll(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(done).catch(done.fail); }); - it('initializes a field', (done) => { + it('initializes a field', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar', 'baz']); - object.save().then(() => { - const query = new Parse.Query('TestObject'); - return query.get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 3); - assert.equal(strings[0], 'foo'); - assert.equal(strings[1], 'bar'); - assert.equal(strings[2], 'baz'); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query('TestObject'); + return query.get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 3); + assert.equal(strings[0], 'foo'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); + done(); + }); }); - it('adds values', (done) => { + it('adds values', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - object.add('strings', 'foo'); - object.add('strings', 'bar'); - object.add('strings', 'baz'); - return object.save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - return query.get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 4); - assert.equal(strings[0], 'foo'); - assert.equal(strings[1], 'foo'); - assert.equal(strings[2], 'bar'); - assert.equal(strings[3], 'baz'); - done(); - }); + object + .save() + .then(() => { + object.add('strings', 'foo'); + object.add('strings', 'bar'); + object.add('strings', 'baz'); + return object.save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + return query.get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 4); + assert.equal(strings[0], 'foo'); + assert.equal(strings[1], 'foo'); + assert.equal(strings[2], 'bar'); + assert.equal(strings[3], 'baz'); + done(); + }); }); - it('adds values on a fresh object', (done) => { + it('adds values on a fresh object', done => { const object = new Parse.Object('TestObject'); object.add('strings', 'foo'); object.add('strings', 'bar'); object.add('strings', 'baz'); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 3); - assert.equal(strings[0], 'foo'); - assert.equal(strings[1], 'bar'); - assert.equal(strings[2], 'baz'); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 3); + assert.equal(strings[0], 'foo'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); + done(); + }); }); - it('sets then adds objects', (done) => { + it('sets then adds objects', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - object.set('strings', ['bar']); - object.add('strings', 'bar'); - object.add('strings', 'baz'); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 3); - assert.equal(strings[0], 'bar'); - assert.equal(strings[1], 'bar'); - assert.equal(strings[2], 'baz'); - done(); - }); + object + .save() + .then(() => { + object.set('strings', ['bar']); + object.add('strings', 'bar'); + object.add('strings', 'baz'); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 3); + assert.equal(strings[0], 'bar'); + assert.equal(strings[1], 'bar'); + assert.equal(strings[2], 'baz'); + done(); + }); }); - it('adds values atomically', (done) => { + it('adds values atomically', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - assert(o !== object); - o.add('strings', 'bar'); - o.add('strings', 'baz'); - object.add('strings', 'bar'); - object.add('strings', 'baz'); - return o.save(); - }).then(() => { - assert(object.dirty()); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 5); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + assert(o !== object); + o.add('strings', 'bar'); + o.add('strings', 'baz'); + object.add('strings', 'bar'); + object.add('strings', 'baz'); + return o.save(); + }) + .then(() => { + assert(object.dirty()); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 5); + done(); + }); }); - it('adds unique values', (done) => { + it('adds unique values', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - object.addUnique('strings', 'foo'); - object.addUnique('strings', 'bar'); - object.addUnique('strings', 'foo'); - object.addUnique('strings', 'baz'); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - strings.sort(); - assert.equal(strings.length, 3); - assert.equal(strings[0], 'bar'); - assert.equal(strings[1], 'baz'); - assert.equal(strings[2], 'foo'); - done(); - }); + object + .save() + .then(() => { + object.addUnique('strings', 'foo'); + object.addUnique('strings', 'bar'); + object.addUnique('strings', 'foo'); + object.addUnique('strings', 'baz'); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + strings.sort(); + assert.equal(strings.length, 3); + assert.equal(strings[0], 'bar'); + assert.equal(strings[1], 'baz'); + assert.equal(strings[2], 'foo'); + done(); + }); }); - it('adds unique values on a fresh object', (done) => { + it('adds unique values on a fresh object', done => { const object = new Parse.Object('TestObject'); object.addUnique('strings', 'foo'); object.addUnique('strings', 'bar'); object.addUnique('strings', 'foo'); object.addUnique('strings', 'baz'); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - strings.sort(); - assert.equal(strings.length, 3); - assert.equal(strings[0], 'bar'); - assert.equal(strings[1], 'baz'); - assert.equal(strings[2], 'foo'); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + strings.sort(); + assert.equal(strings.length, 3); + assert.equal(strings[0], 'bar'); + assert.equal(strings[1], 'baz'); + assert.equal(strings[2], 'foo'); + done(); + }); }); it('adds unique values after a set', () => { const object = new Parse.Object('TestObject'); - object.set('numbers', [1,2,3,3,4,4]); - [1,4,4,5].forEach((number) => { + object.set('numbers', [1, 2, 3, 3, 4, 4]); + [1, 4, 4, 5].forEach(number => { object.addUnique('numbers', number); }); assert.equal(object.get('numbers').length, 7); }); - it('adds unique values atomically', (done) => { + it('adds unique values atomically', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - o.addUnique('strings', 'bar'); - o.addUnique('strings', 'baz'); - object.addUnique('strings', 'baz'); - object.addUnique('strings', 'bat'); - return o.save(); - }).then(() => { - assert(object.dirty()); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - strings.sort(); - assert.equal(strings.length, 4); - assert.equal(strings[0], 'bar'); - assert.equal(strings[1], 'bat'); - assert.equal(strings[2], 'baz'); - assert.equal(strings[3], 'foo'); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + o.addUnique('strings', 'bar'); + o.addUnique('strings', 'baz'); + object.addUnique('strings', 'baz'); + object.addUnique('strings', 'bat'); + return o.save(); + }) + .then(() => { + assert(object.dirty()); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + strings.sort(); + assert.equal(strings.length, 4); + assert.equal(strings[0], 'bar'); + assert.equal(strings[1], 'bat'); + assert.equal(strings[2], 'baz'); + assert.equal(strings[3], 'foo'); + done(); + }); }); - it('removes values', (done) => { + it('removes values', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'foo', 'bar', 'baz']); - object.save().then(() => { - object.remove('strings', 'foo'); - object.remove('strings', 'baz'); - object.remove('strings', 'bat'); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 1); - assert.equal(strings[0], 'bar'); - done(); - }); + object + .save() + .then(() => { + object.remove('strings', 'foo'); + object.remove('strings', 'baz'); + object.remove('strings', 'bat'); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 1); + assert.equal(strings[0], 'bar'); + done(); + }); }); - it('sets then removes values', (done) => { + it('sets then removes values', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo']); - object.save().then(() => { - object.set('strings', ['bar', 'baz', 'bat']); - object.remove('strings', 'bar'); - object.remove('strings', 'baz'); - object.remove('strings', 'zzz'); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 1); - assert.equal(strings[0], 'bat'); - done(); - }); + object + .save() + .then(() => { + object.set('strings', ['bar', 'baz', 'bat']); + object.remove('strings', 'bar'); + object.remove('strings', 'baz'); + object.remove('strings', 'zzz'); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 1); + assert.equal(strings[0], 'bat'); + done(); + }); }); - it('removes values on a fresh object', (done) => { + it('removes values on a fresh object', done => { const object = new Parse.Object('TestObject'); object.remove('strings', 'foo'); object.remove('strings', 'baz'); object.remove('strings', 'bat'); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - assert.equal(strings.length, 0); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + assert.equal(strings.length, 0); + done(); + }); }); - it('removes values atomically', (done) => { + it('removes values atomically', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'foo', 'bar', 'baz']); - object.save().then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - o.remove('strings', 'foo'); - o.remove('strings', 'zzz'); - object.remove('strings', 'bar'); - object.remove('strings', 'zzz'); - return o.save(); - }).then(() => { - assert(object.dirty()); - return object.save(); - }).then(() => { - return new Parse.Query('TestObject').get(object.id); - }).then((o) => { - const strings = o.get('strings'); - strings.sort(); - assert.equal(strings.length, 1); - assert.equal(strings[0], 'baz'); - done(); - }); + object + .save() + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + o.remove('strings', 'foo'); + o.remove('strings', 'zzz'); + object.remove('strings', 'bar'); + object.remove('strings', 'zzz'); + return o.save(); + }) + .then(() => { + assert(object.dirty()); + return object.save(); + }) + .then(() => { + return new Parse.Query('TestObject').get(object.id); + }) + .then(o => { + const strings = o.get('strings'); + strings.sort(); + assert.equal(strings.length, 1); + assert.equal(strings[0], 'baz'); + done(); + }); }); - it('fails when combining add unique with add', (done) => { + it('fails when combining add unique with add', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.add('strings', 'bar'); - object.addUnique('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.add('strings', 'bar'); + object.addUnique('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); + done(); + }); }); - it('fails when combining add with add unique', (done) => { + it('fails when combining add with add unique', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.addUnique('strings', 'bar'); - object.add('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.addUnique('strings', 'bar'); + object.add('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); + done(); + }); }); - it('fails when combining remove with add', (done) => { + it('fails when combining remove with add', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.add('strings', 'bar'); - object.remove('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.add('strings', 'bar'); + object.remove('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); + done(); + }); }); - it('fails when combining add with remove', (done) => { + it('fails when combining add with remove', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.remove('strings', 'bar'); - object.add('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.remove('strings', 'bar'); + object.add('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge Add Op with the previous Op'); + done(); + }); }); - it('fails when combining remove with add unique', (done) => { + it('fails when combining remove with add unique', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.addUnique('strings', 'bar'); - object.remove('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.addUnique('strings', 'bar'); + object.remove('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge Remove Op with the previous Op'); + done(); + }); }); - it('fails when combining remove with add unique', (done) => { + it('fails when combining remove with add unique', done => { const object = new Parse.Object('TestObject'); object.set('strings', ['foo', 'bar']); - object.save().then(() => { - object.remove('strings', 'bar'); - object.addUnique('strings', 'bar'); - }).catch((e) => { - assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); - done(); - }); + object + .save() + .then(() => { + object.remove('strings', 'bar'); + object.addUnique('strings', 'bar'); + }) + .catch(e => { + assert.equal(e.message, 'Cannot merge AddUnique Op with the previous Op'); + done(); + }); }); - it('adds unique objects by id', (done) => { + it('adds unique objects by id', done => { const snowflake = new Parse.Object('Snowflake'); const pocket = new Parse.Object('Pocket'); snowflake.set('color', 'white'); - snowflake.save().then(() => { - pocket.set('snowflakes', [snowflake]); - const snowflakeQuery = new Parse.Query('Snowflake'); - return snowflakeQuery.get(snowflake.id); - }).then((flake) => { - pocket.addUnique('snowflakes', flake); - assert.equal(pocket.get('snowflakes').length, 1); - return pocket.save(); - }).then(() => { - const pocketQuery = new Parse.Query('Pocket'); - pocketQuery.include('snowflakes'); - return pocketQuery.get(pocket.id); - }).then((newPocket) => { - assert.notEqual(pocket, newPocket); - assert.equal(newPocket.get('snowflakes').length, 1); - const flake = newPocket.get('snowflakes')[0]; - assert.equal(flake.get('color'), 'white'); - done(); - }); + snowflake + .save() + .then(() => { + pocket.set('snowflakes', [snowflake]); + const snowflakeQuery = new Parse.Query('Snowflake'); + return snowflakeQuery.get(snowflake.id); + }) + .then(flake => { + pocket.addUnique('snowflakes', flake); + assert.equal(pocket.get('snowflakes').length, 1); + return pocket.save(); + }) + .then(() => { + const pocketQuery = new Parse.Query('Pocket'); + pocketQuery.include('snowflakes'); + return pocketQuery.get(pocket.id); + }) + .then(newPocket => { + assert.notEqual(pocket, newPocket); + assert.equal(newPocket.get('snowflakes').length, 1); + const flake = newPocket.get('snowflakes')[0]; + assert.equal(flake.get('color'), 'white'); + done(); + }); }); - it('removes objects by id', (done) => { + it('removes objects by id', done => { const badEgg = new Parse.Object('Egg'); badEgg.set('quality', 'rotten'); const goodEgg = new Parse.Object('Egg'); @@ -371,23 +444,27 @@ describe('Array Operations', () => { ostrichEgg.set('quality', 'huge'); const eggs = [badEgg, goodEgg, ostrichEgg]; const shelf = new Parse.Object('Shelf'); - Parse.Object.saveAll(eggs).then(() => { - shelf.set('eggs', eggs); - const badEggQuery = new Parse.Query('Egg'); - return badEggQuery.get(badEgg.id); - }).then((badEggRef) => { - assert.notEqual(badEgg, badEggRef); - shelf.remove('eggs', badEggRef); - const fetchedEggs = shelf.get('eggs'); - assert.equal(fetchedEggs.length, 2); - assert.equal(fetchedEggs[0].get('quality'), 'good'); - assert.equal(fetchedEggs[1].get('quality'), 'huge'); - return shelf.save(); - }).then(() => { - return shelf.fetch(); - }).then(() => { - assert.equal(shelf.get('eggs').length, 2); - done(); - }); + Parse.Object.saveAll(eggs) + .then(() => { + shelf.set('eggs', eggs); + const badEggQuery = new Parse.Query('Egg'); + return badEggQuery.get(badEgg.id); + }) + .then(badEggRef => { + assert.notEqual(badEgg, badEggRef); + shelf.remove('eggs', badEggRef); + const fetchedEggs = shelf.get('eggs'); + assert.equal(fetchedEggs.length, 2); + assert.equal(fetchedEggs[0].get('quality'), 'good'); + assert.equal(fetchedEggs[1].get('quality'), 'huge'); + return shelf.save(); + }) + .then(() => { + return shelf.fetch(); + }) + .then(() => { + assert.equal(shelf.get('eggs').length, 2); + done(); + }); }); }); diff --git a/integration/test/CustomAuth.js b/integration/test/CustomAuth.js index 97a719a55..a338e669c 100644 --- a/integration/test/CustomAuth.js +++ b/integration/test/CustomAuth.js @@ -1,6 +1,6 @@ /* eslint-disable */ function validateAuthData(authData, options) { - return Promise.resolve({}) + return Promise.resolve({}); } function validateAppId(appIds, authData, options) { diff --git a/integration/test/DirtyTest.js b/integration/test/DirtyTest.js index 5f4be172f..7574d6bf5 100644 --- a/integration/test/DirtyTest.js +++ b/integration/test/DirtyTest.js @@ -9,200 +9,241 @@ const Parent = Parse.Object.extend('Parent'); const Child = Parse.Object.extend('Child'); describe('Dirty Objects', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - clear().then(() => { - done(); - }).catch(done.fail); + clear() + .then(() => { + done(); + }) + .catch(done.fail); }); - it('tracks dirty arrays', (done) => { + it('tracks dirty arrays', done => { const array = [1]; const object = new TestObject(); object.set('scores', array); assert.equal(object.get('scores').length, 1); - object.save().then(() => { - array.push(2); - assert.equal(object.get('scores').length, 2); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('scores').length, 2); - done(); - }).catch(done.fail); + object + .save() + .then(() => { + array.push(2); + assert.equal(object.get('scores').length, 2); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('scores').length, 2); + done(); + }) + .catch(done.fail); }); - it('tracks dirty arrays after fetch', (done) => { + it('tracks dirty arrays after fetch', done => { const object = new TestObject(); object.set('scores', [1]); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - const array = o.get('scores'); - array.push(2); - return o.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('scores').length, 2); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + const array = o.get('scores'); + array.push(2); + return o.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('scores').length, 2); + done(); + }); }); - it('tracks dirty objects', (done) => { - const dict = {player1: 1}; + it('tracks dirty objects', done => { + const dict = { player1: 1 }; const object = new TestObject(); object.set('scoreMap', dict); - object.save().then(() => { - dict.player2 = 2; - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(Object.keys(o.get('scoreMap')).length, 2); - done(); - }); + object + .save() + .then(() => { + dict.player2 = 2; + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(Object.keys(o.get('scoreMap')).length, 2); + done(); + }); }); - it('tracks dirty objects after fetch', (done) => { - const dict = {player1: 1}; + it('tracks dirty objects after fetch', done => { + const dict = { player1: 1 }; const object = new TestObject(); object.set('scoreMap', dict); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - const dictAgain = o.get('scoreMap'); - dictAgain.player2 = 2; - return o.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(Object.keys(o.get('scoreMap')).length, 2); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + const dictAgain = o.get('scoreMap'); + dictAgain.player2 = 2; + return o.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(Object.keys(o.get('scoreMap')).length, 2); + done(); + }); }); - it('tracks dirty geo points', (done) => { + it('tracks dirty geo points', done => { const geo = new Parse.GeoPoint(5, 5); const object = new TestObject(); object.set('location', geo); - object.save().then(() => { - geo.latitude = 10; - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('location').latitude, 10); - done(); - }); + object + .save() + .then(() => { + geo.latitude = 10; + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('location').latitude, 10); + done(); + }); }); - it('tracks dirty geo points on fresh objects', (done) => { + it('tracks dirty geo points on fresh objects', done => { const geo = new Parse.GeoPoint(1.0, 1.0); const object = new TestObject(); object.set('location', geo); geo.latitude = 2.0; - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('location').latitude, 2); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('location').latitude, 2); + done(); + }); }); - it('does not resave relations with dirty children', (done) => { + it('does not resave relations with dirty children', done => { const parent = new Parent(); const child = new Child(); let newChild; let parentAgain; child.set('ghostbuster', 'peter'); parent.set('child', child); - parent.save().then(() => { - assert.equal(parent.get('child'), child); - assert.equal(child.get('ghostbuster'), 'peter'); - - const query = new Parse.Query(Parent); - return query.get(parent.id); - }).then((again) => { - parentAgain = again; - newChild = new Child(); - newChild.set('ghostbuster', 'ray'); - parentAgain.set('child', newChild); - return parentAgain.save(); - }).then(() => { - assert.equal(parent.get('child'), child); - assert.equal(parentAgain.get('child'), newChild); - assert.equal(child.get('ghostbuster'), 'peter'); - assert.equal(newChild.get('ghostbuster'), 'ray'); - - // Now parent's child is newChild. If we change the original - // child, it shouldn't affect parent. - child.set('ghostbuster', 'egon'); - assert.equal(parent.get('child').get('ghostbuster'), 'egon'); - - return parent.save(); - }).then(()=> { - assert.equal(parent.get('child'), child); - assert.equal(parentAgain.get('child'), newChild); - assert.equal(child.get('ghostbuster'), 'egon'); - assert.equal(newChild.get('ghostbuster'), 'ray'); - - const query = new Parse.Query(Parent); - return query.get(parent.id); - }).then((yetAgain) => { - assert.equal(parent.get('child'), child); - assert.equal(parentAgain.get('child'), newChild); - assert.equal(yetAgain.get('child').id, newChild.id); - assert.equal(child.get('ghostbuster'), 'egon'); - assert.equal(newChild.get('ghostbuster'), 'ray'); - - const newChildAgain = yetAgain.get('child'); - assert.equal(newChildAgain.id, newChild.id); - return newChildAgain.fetch(); - }).then((c) => { - assert.equal(c.get('ghostbuster'), 'ray'); - done(); - }); + parent + .save() + .then(() => { + assert.equal(parent.get('child'), child); + assert.equal(child.get('ghostbuster'), 'peter'); + + const query = new Parse.Query(Parent); + return query.get(parent.id); + }) + .then(again => { + parentAgain = again; + newChild = new Child(); + newChild.set('ghostbuster', 'ray'); + parentAgain.set('child', newChild); + return parentAgain.save(); + }) + .then(() => { + assert.equal(parent.get('child'), child); + assert.equal(parentAgain.get('child'), newChild); + assert.equal(child.get('ghostbuster'), 'peter'); + assert.equal(newChild.get('ghostbuster'), 'ray'); + + // Now parent's child is newChild. If we change the original + // child, it shouldn't affect parent. + child.set('ghostbuster', 'egon'); + assert.equal(parent.get('child').get('ghostbuster'), 'egon'); + + return parent.save(); + }) + .then(() => { + assert.equal(parent.get('child'), child); + assert.equal(parentAgain.get('child'), newChild); + assert.equal(child.get('ghostbuster'), 'egon'); + assert.equal(newChild.get('ghostbuster'), 'ray'); + + const query = new Parse.Query(Parent); + return query.get(parent.id); + }) + .then(yetAgain => { + assert.equal(parent.get('child'), child); + assert.equal(parentAgain.get('child'), newChild); + assert.equal(yetAgain.get('child').id, newChild.id); + assert.equal(child.get('ghostbuster'), 'egon'); + assert.equal(newChild.get('ghostbuster'), 'ray'); + + const newChildAgain = yetAgain.get('child'); + assert.equal(newChildAgain.id, newChild.id); + return newChildAgain.fetch(); + }) + .then(c => { + assert.equal(c.get('ghostbuster'), 'ray'); + done(); + }); }); - it('does not dirty two-way pointers on saveAll', (done) => { + it('does not dirty two-way pointers on saveAll', done => { const parent = new Parent(); const child = new Child(); - child.save().then(() => { - child.set('property', 'x'); - parent.set('children', [child]); - child.set('parent', parent); - return Parse.Object.saveAll([parent, child]); - }).then((results) => { - assert.equal(results[0].dirty(), false); - assert.equal(results[1].dirty(), false); - done(); - }); + child + .save() + .then(() => { + child.set('property', 'x'); + parent.set('children', [child]); + child.set('parent', parent); + return Parse.Object.saveAll([parent, child]); + }) + .then(results => { + assert.equal(results[0].dirty(), false); + assert.equal(results[1].dirty(), false); + done(); + }); }); - it('unset fields should not stay dirty', (done) => { + it('unset fields should not stay dirty', done => { const object = new TestObject(); - object.save({ foo: 'bar' }).then(() => { - assert.equal(object.dirty(), false); - object.unset('foo'); - assert.equal(object.dirty(), true); - - return object.save(); - }).then(() => { - assert.equal(object.dirty(), false); - done(); - }); + object + .save({ foo: 'bar' }) + .then(() => { + assert.equal(object.dirty(), false); + object.unset('foo'); + assert.equal(object.dirty(), true); + + return object.save(); + }) + .then(() => { + assert.equal(object.dirty(), false); + done(); + }); }); }); diff --git a/integration/test/IdempotencyTest.js b/integration/test/IdempotencyTest.js index 73544f0e4..0ce710165 100644 --- a/integration/test/IdempotencyTest.js +++ b/integration/test/IdempotencyTest.js @@ -14,14 +14,14 @@ function DuplicateXHR(requestId) { xhr.send = function () { this.setRequestHeader('X-Parse-Request-Id', requestId); send.apply(this, arguments); - } + }; return xhr; } return XHRWrapper; } describe('Idempotency', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); @@ -34,8 +34,12 @@ describe('Idempotency', () => { it('handle duplicate cloud code function request', async () => { RESTController._setXHR(DuplicateXHR('1234')); await Parse.Cloud.run('CloudFunctionIdempotency'); - await expectAsync(Parse.Cloud.run('CloudFunctionIdempotency')).toBeRejectedWithError('Duplicate request'); - await expectAsync(Parse.Cloud.run('CloudFunctionIdempotency')).toBeRejectedWithError('Duplicate request'); + await expectAsync(Parse.Cloud.run('CloudFunctionIdempotency')).toBeRejectedWithError( + 'Duplicate request' + ); + await expectAsync(Parse.Cloud.run('CloudFunctionIdempotency')).toBeRejectedWithError( + 'Duplicate request' + ); const query = new Parse.Query(Item); const results = await query.find(); @@ -46,7 +50,9 @@ describe('Idempotency', () => { RESTController._setXHR(DuplicateXHR('1234')); const params = { startedBy: 'Monty Python' }; const jobStatusId = await Parse.Cloud.startJob('CloudJob1', params); - await expectAsync(Parse.Cloud.startJob('CloudJob1', params)).toBeRejectedWithError('Duplicate request'); + await expectAsync(Parse.Cloud.startJob('CloudJob1', params)).toBeRejectedWithError( + 'Duplicate request' + ); const jobStatus = await Parse.Cloud.getJobStatus(jobStatusId); expect(jobStatus.get('status')).toBe('succeeded'); diff --git a/integration/test/IncrementTest.js b/integration/test/IncrementTest.js index cd0e4f51e..bb3fa612a 100644 --- a/integration/test/IncrementTest.js +++ b/integration/test/IncrementTest.js @@ -7,28 +7,34 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Increment', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - clear().then(() => { - done(); - }).catch(done.fail); + clear() + .then(() => { + done(); + }) + .catch(done.fail); }); - it('can increment a field', (done) => { + it('can increment a field', done => { const object = new TestObject(); object.set('score', 1); - object.save().then(() => { - object.increment('score'); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 2); - done(); - }); + object + .save() + .then(() => { + object.increment('score'); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 2); + done(); + }); }); it('can increment on a fresh object', () => { @@ -38,120 +44,149 @@ describe('Increment', () => { assert.equal(object.get('score'), 2); }); - it('can increment by a value', (done) => { + it('can increment by a value', done => { const object = new TestObject(); object.set('score', 1); - object.save().then(() => { - object.increment('score', 10); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 11); - done(); - }); + object + .save() + .then(() => { + object.increment('score', 10); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 11); + done(); + }); }); - it('can increment with negative numbers', (done) => { + it('can increment with negative numbers', done => { const object = new TestObject(); object.set('score', 1); - object.save().then(() => { - object.increment('score', -1); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 0); - done(); - }); + object + .save() + .then(() => { + object.increment('score', -1); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 0); + done(); + }); }); - it('can increment with floats', (done) => { + it('can increment with floats', done => { const object = new TestObject(); object.set('score', 1.0); - object.save().then(() => { - object.increment('score', 1.5); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 2.5); - done(); - }); + object + .save() + .then(() => { + object.increment('score', 1.5); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 2.5); + done(); + }); }); - it('increments atomically', (done) => { + it('increments atomically', done => { const object = new TestObject(); object.set('score', 1); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - object.increment('score'); - o.increment('score'); - return o.save(); - }).then(() => { - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 3); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + object.increment('score'); + o.increment('score'); + return o.save(); + }) + .then(() => { + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 3); + done(); + }); }); - it('gets a new value back on increment', (done) => { + it('gets a new value back on increment', done => { const object = new TestObject(); let objectAgain; object.set('score', 1); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - objectAgain = o; - assert.equal(o.get('score'), 1); - object.increment('score'); - assert.equal(object.get('score'), 2); - return object.save(); - }).then(() => { - assert.equal(object.get('score'), 2); - objectAgain.increment('score'); - return objectAgain.save(); - }).then(() => { - assert.equal(objectAgain.get('score'), 3); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + objectAgain = o; + assert.equal(o.get('score'), 1); + object.increment('score'); + assert.equal(object.get('score'), 2); + return object.save(); + }) + .then(() => { + assert.equal(object.get('score'), 2); + objectAgain.increment('score'); + return objectAgain.save(); + }) + .then(() => { + assert.equal(objectAgain.get('score'), 3); + done(); + }); }); - it('can combine increment with other updates', (done) => { + it('can combine increment with other updates', done => { const object = new TestObject(); object.set('score', 1); object.set('name', 'hungry'); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - o.increment('score'); - o.set('name', 'parse'); - return o.save(); - }).then(() => { - object.increment('score'); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('name'), 'parse'); - assert.equal(o.get('score'), 3); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + o.increment('score'); + o.set('name', 'parse'); + return o.save(); + }) + .then(() => { + object.increment('score'); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('name'), 'parse'); + assert.equal(o.get('score'), 3); + done(); + }); }); - it('does not increment non-numbers', (done) => { + it('does not increment non-numbers', done => { const object = new TestObject(); object.set('not_score', 'foo'); object.save().then(() => { @@ -163,65 +198,81 @@ describe('Increment', () => { }); }); - it('can increment on a deleted field', (done) => { + it('can increment on a deleted field', done => { const object = new TestObject(); object.set('score', 1); - object.save().then(() => { - object.unset('score'); - object.increment('score'); - assert.equal(object.get('score'), 1); - return object.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 1); - done(); - }); + object + .save() + .then(() => { + object.unset('score'); + object.increment('score'); + assert.equal(object.get('score'), 1); + return object.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 1); + done(); + }); }); - it('can increment with an empty field on a fresh object', (done) => { + it('can increment with an empty field on a fresh object', done => { const object = new TestObject(); object.increment('score'); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - o.get('score', 1); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + o.get('score', 1); + done(); + }); }); - it('can increment with an empty field', (done) => { + it('can increment with an empty field', done => { const object = new TestObject(); let objectAgain; - object.save().then(() => { - object.increment('score'); - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - objectAgain = o; - o.increment('score'); - return object.save(); - }).then(() => { - return objectAgain.save(); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('score'), 2); - done(); - }); + object + .save() + .then(() => { + object.increment('score'); + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + objectAgain = o; + o.increment('score'); + return object.save(); + }) + .then(() => { + return objectAgain.save(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('score'), 2); + done(); + }); }); - it('solidifies the type by incrementing', (done) => { + it('solidifies the type by incrementing', done => { const object = new TestObject(); object.increment('numeric'); - object.save().then(() => { - object.set('numeric', 'x'); - return object.save(); - }).catch(() => { - done(); - }); + object + .save() + .then(() => { + object.set('numeric', 'x'); + return object.save(); + }) + .catch(() => { + done(); + }); }); }); diff --git a/integration/test/ParseACLTest.js b/integration/test/ParseACLTest.js index f021a02b0..be8a2b9fe 100644 --- a/integration/test/ParseACLTest.js +++ b/integration/test/ParseACLTest.js @@ -7,14 +7,23 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Parse.ACL', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); Parse.User.enableUnsafeCurrentUser(); - clear().then(() => { - Parse.User.logOut().then(() => { done() }, () => { done() }); - }).catch(done.fail); + clear() + .then(() => { + Parse.User.logOut().then( + () => { + done(); + }, + () => { + done(); + } + ); + }) + .catch(done.fail); }); it('acl must be valid', () => { @@ -409,7 +418,7 @@ describe('Parse.ACL', () => { it('can grant delete access to another user', async () => { const object = new TestObject(); - const user1 = await Parse.User.signUp('ggg', 'password') + const user1 = await Parse.User.signUp('ggg', 'password'); await Parse.User.logOut(); const user2 = await Parse.User.signUp('hhh', 'password'); @@ -517,7 +526,7 @@ describe('Parse.ACL', () => { it('allows access with an empty acl', async () => { await Parse.User.signUp('tdurden', 'mayhem', { ACL: new Parse.ACL(), - foo: 'bar' + foo: 'bar', }); await Parse.User.logOut(); const user = await Parse.User.logIn('tdurden', 'mayhem'); diff --git a/integration/test/ParseCloudTest.js b/integration/test/ParseCloudTest.js index 01332c8c8..7ddedf3c9 100644 --- a/integration/test/ParseCloudTest.js +++ b/integration/test/ParseCloudTest.js @@ -6,61 +6,81 @@ const Parse = require('../../node'); const sleep = require('./sleep'); describe('Parse Cloud', () => { - beforeAll((done) => { + beforeAll(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - clear().then(() => { done() }, () => { done() }); + clear().then( + () => { + done(); + }, + () => { + done(); + } + ); }); - it('run function', (done) => { + it('run function', done => { const params = { key1: 'value2', key2: 'value1' }; - Parse.Cloud.run('bar', params).then((result) => { - assert.equal('Foo', result); - done(); - }).catch(done.fail); + Parse.Cloud.run('bar', params) + .then(result => { + assert.equal('Foo', result); + done(); + }) + .catch(done.fail); }); - it('run function with user', (done) => { + it('run function with user', done => { const params = { key1: 'value2', key2: 'value1' }; const user = new Parse.User(); user.setUsername('someuser'); user.setPassword('somepassword'); - user.signUp().then(() => { - return Parse.Cloud.run('bar', params); - }).then((resp) => { - assert.equal('Foo', resp); - return user.destroy({ useMasterKey: true }); - }).then(() => { - done(); - }).catch(done.fail); + user + .signUp() + .then(() => { + return Parse.Cloud.run('bar', params); + }) + .then(resp => { + assert.equal('Foo', resp); + return user.destroy({ useMasterKey: true }); + }) + .then(() => { + done(); + }) + .catch(done.fail); }); - it('run function failed', (done) => { + it('run function failed', done => { const params = { key1: 'value1', key2: 'value2' }; - Parse.Cloud.run('bar', params).then(done.fail).catch((error) => { - assert.equal(error.code, Parse.Error.SCRIPT_FAILED); - done(); - }); + Parse.Cloud.run('bar', params) + .then(done.fail) + .catch(error => { + assert.equal(error.code, Parse.Error.SCRIPT_FAILED); + done(); + }); }); - it('run function name fail', (done) => { + it('run function name fail', done => { const params = { key1: 'value1' }; - Parse.Cloud.run('unknown_function', params).then(done.fail).catch((error) => { - assert.equal(error.message, 'Invalid function: "unknown_function"'); - done(); - }); + Parse.Cloud.run('unknown_function', params) + .then(done.fail) + .catch(error => { + assert.equal(error.message, 'Invalid function: "unknown_function"'); + done(); + }); }); - it('run function with geopoint params does not fail', (done) => { + it('run function with geopoint params does not fail', done => { const params = { key1: new Parse.GeoPoint(50, 50) }; - Parse.Cloud.run('unknown_function', params).then(null).catch((error) => { - assert.equal(error.message, 'Invalid function: "unknown_function"'); - done(); - }); + Parse.Cloud.run('unknown_function', params) + .then(null) + .catch(error => { + assert.equal(error.message, 'Invalid function: "unknown_function"'); + done(); + }); }); - it('run function with object params fail', (done) => { + it('run function with object params fail', done => { const object = new Parse.Object('TestClass'); const params = { key1: object }; try { @@ -71,22 +91,24 @@ describe('Parse Cloud', () => { } }); - it('run function with undefined', (done) => { - Parse.Cloud.run('CloudFunctionUndefined', {}).then((result) => { + it('run function with undefined', done => { + Parse.Cloud.run('CloudFunctionUndefined', {}).then(result => { assert.strictEqual(result, undefined); done(); }); }); - it('run job', (done) => { + it('run job', done => { const params = { startedBy: 'Monty Python' }; - Parse.Cloud.startJob('CloudJob1', params).then((jobStatusId) => { - return Parse.Cloud.getJobStatus(jobStatusId); - }).then((jobStatus) => { - assert.equal(jobStatus.get('status'), 'succeeded'); - assert.equal(jobStatus.get('params').startedBy, 'Monty Python'); - done(); - }); + Parse.Cloud.startJob('CloudJob1', params) + .then(jobStatusId => { + return Parse.Cloud.getJobStatus(jobStatusId); + }) + .then(jobStatus => { + assert.equal(jobStatus.get('status'), 'succeeded'); + assert.equal(jobStatus.get('params').startedBy, 'Monty Python'); + done(); + }); }); it('run long job', async () => { @@ -101,36 +123,42 @@ describe('Parse Cloud', () => { assert.equal(jobStatus.get('status'), 'succeeded'); }); - it('run bad job', (done) => { - Parse.Cloud.startJob('bad_job').then(null).catch((error) => { - assert.equal(error.code, Parse.Error.SCRIPT_FAILED); - assert.equal(error.message, 'Invalid job.'); - done(); - }); + it('run bad job', done => { + Parse.Cloud.startJob('bad_job') + .then(null) + .catch(error => { + assert.equal(error.code, Parse.Error.SCRIPT_FAILED); + assert.equal(error.message, 'Invalid job.'); + done(); + }); }); - it('run failing job', (done) => { - Parse.Cloud.startJob('CloudJobFailing').then((jobStatusId) => { - return Parse.Cloud.getJobStatus(jobStatusId); - }).then((jobStatus) => { - assert.equal(jobStatus.get('status'), 'failed'); - assert.equal(jobStatus.get('message'), 'cloud job failed'); - done(); - }); + it('run failing job', done => { + Parse.Cloud.startJob('CloudJobFailing') + .then(jobStatusId => { + return Parse.Cloud.getJobStatus(jobStatusId); + }) + .then(jobStatus => { + assert.equal(jobStatus.get('status'), 'failed'); + assert.equal(jobStatus.get('message'), 'cloud job failed'); + done(); + }); }); - it('get jobs data', (done) => { - Parse.Cloud.getJobsData().then((result) => { + it('get jobs data', done => { + Parse.Cloud.getJobsData().then(result => { assert.equal(result.in_use.length, 0); assert.equal(result.jobs.length, 3); done(); }); }); - it('invalid job status id', (done) => { - Parse.Cloud.getJobStatus('not-a-real-id').then(null).catch((error) => { - assert.equal(error.message, 'Object not found.'); - done(); - }); + it('invalid job status id', done => { + Parse.Cloud.getJobStatus('not-a-real-id') + .then(null) + .catch(error => { + assert.equal(error.message, 'Object not found.'); + done(); + }); }); }); diff --git a/integration/test/ParseConfigTest.js b/integration/test/ParseConfigTest.js index a6b1a7960..857c09759 100644 --- a/integration/test/ParseConfigTest.js +++ b/integration/test/ParseConfigTest.js @@ -5,14 +5,11 @@ const clear = require('./clear'); const Parse = require('../../node'); function testConfig() { - return Parse.Config.save( - { internal: "i", string: "s", number: 12 }, - { internal: true } - ); + return Parse.Config.save({ internal: 'i', string: 's', number: 12 }, { internal: true }); } describe('Parse Config', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); diff --git a/integration/test/ParseFileTest.js b/integration/test/ParseFileTest.js index 2bc7daa4d..3e974d15b 100644 --- a/integration/test/ParseFileTest.js +++ b/integration/test/ParseFileTest.js @@ -5,7 +5,7 @@ const clear = require('./clear'); const Parse = require('../../node'); describe('Parse.File', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); @@ -14,7 +14,8 @@ describe('Parse.File', () => { it('can save file with uri', async () => { // Try https - const parseLogo = 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; + const parseLogo = + 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; const file1 = new Parse.File('parse-server-logo', { uri: parseLogo }); await file1.save(); @@ -40,7 +41,8 @@ describe('Parse.File', () => { }); it('can cancel save file with uri', async () => { - const parseLogo = 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; + const parseLogo = + 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; const file = new Parse.File('parse-server-logo', { uri: parseLogo }); file.save().then(() => { assert.equal(file.name(), undefined); @@ -65,7 +67,7 @@ describe('Parse.File', () => { assert.equal(data, 'ParseA=='); file._data = null; await file.save(); - assert.equal(file._data, null) + assert.equal(file._data, null); data = await file.getData(); assert.equal(data, 'ParseA=='); }); @@ -76,24 +78,27 @@ describe('Parse.File', () => { assert.equal(data, 'ParseA=='); file._data = null; await file.save(); - assert.equal(file._data, null) + assert.equal(file._data, null); data = await file.getData(); assert.equal(data, 'ParseA=='); }); it('can get file data from full base64', async () => { - const file = new Parse.File('parse-server-logo', { base64: 'data:image/jpeg;base64,ParseA==' }); + const file = new Parse.File('parse-server-logo', { + base64: 'data:image/jpeg;base64,ParseA==', + }); let data = await file.getData(); assert.equal(data, 'ParseA=='); file._data = null; await file.save(); - assert.equal(file._data, null) + assert.equal(file._data, null); data = await file.getData(); assert.equal(data, 'ParseA=='); }); it('can delete file', async () => { - const parseLogo = 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; + const parseLogo = + 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; const file = new Parse.File('parse-server-logo', { uri: parseLogo }); await file.save(); const data = await file.getData(); @@ -105,7 +110,8 @@ describe('Parse.File', () => { }); it('can handle delete file error', async () => { - const parseLogo = 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; + const parseLogo = + 'https://raw.githubusercontent.com/parse-community/parse-server/master/.github/parse-server-logo.png'; const file = new Parse.File('parse-server-logo', { uri: parseLogo }); try { await file.destroy(); diff --git a/integration/test/ParseGeoBoxTest.js b/integration/test/ParseGeoBoxTest.js index 17bf62f71..377bc757d 100644 --- a/integration/test/ParseGeoBoxTest.js +++ b/integration/test/ParseGeoBoxTest.js @@ -14,11 +14,11 @@ describe('Geo Box', () => { Parse.Storage._clear(); }); - beforeEach((done) => { + beforeEach(done => { clear().then(done).catch(done); }); - it('can query geo boxes', (done) => { + it('can query geo boxes', done => { const caltrainStationLocation = new Parse.GeoPoint(37.776346, -122.394218); const caltrainStation = new Parse.Object('Location'); caltrainStation.set('location', caltrainStationLocation); @@ -29,18 +29,21 @@ describe('Geo Box', () => { santaClara.set('location', santaClaraLocation); santaClara.set('name', 'santa clara'); - Parse.Object.saveAll([caltrainStation, santaClara]).then(() => { - const query = new Parse.Query('Location'); - query.withinGeoBox('location', southwestOfSF, northeastOfSF); - return query.find(); - }).then((objectsInSF) => { - assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get('name'), 'caltrain'); - done(); - }).catch(done.fail); + Parse.Object.saveAll([caltrainStation, santaClara]) + .then(() => { + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); + return query.find(); + }) + .then(objectsInSF => { + assert.equal(objectsInSF.length, 1); + assert.equal(objectsInSF[0].get('name'), 'caltrain'); + done(); + }) + .catch(done.fail); }); - it('can swap geo box corners', (done) => { + it('can swap geo box corners', done => { const caltrainStationLocation = new Parse.GeoPoint(37.776346, -122.394218); const caltrainStation = new Parse.Object('Location'); caltrainStation.set('location', caltrainStationLocation); @@ -54,18 +57,21 @@ describe('Geo Box', () => { const southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398); const northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962); - Parse.Object.saveAll([caltrainStation, santaClara]).then(() => { - const query = new Parse.Query('Location'); - query.withinGeoBox('location', northeastOfSF, southwestOfSF); - return query.find(); - }).then((objectsInSF) => { - assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get('name'), 'caltrain'); - done(); - }).catch(done.fail); + Parse.Object.saveAll([caltrainStation, santaClara]) + .then(() => { + const query = new Parse.Query('Location'); + query.withinGeoBox('location', northeastOfSF, southwestOfSF); + return query.find(); + }) + .then(objectsInSF => { + assert.equal(objectsInSF.length, 1); + assert.equal(objectsInSF[0].get('name'), 'caltrain'); + done(); + }) + .catch(done.fail); }); - it('can swap longitude', (done) => { + it('can swap longitude', done => { const caltrainStationLocation = new Parse.GeoPoint(37.776346, -122.394218); const caltrainStation = new Parse.Object('Location'); caltrainStation.set('location', caltrainStationLocation); @@ -76,18 +82,21 @@ describe('Geo Box', () => { santaClara.set('location', santaClaraLocation); santaClara.set('name', 'santa clara'); - Parse.Object.saveAll([caltrainStation, santaClara]).then(() => { - const query = new Parse.Query('Location'); - query.withinGeoBox('location', southwestOfSF, northeastOfSF); - return query.find(); - }).then((objectsInSF) => { - assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get('name'), 'caltrain'); - done(); - }).catch(done.fail); + Parse.Object.saveAll([caltrainStation, santaClara]) + .then(() => { + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); + return query.find(); + }) + .then(objectsInSF => { + assert.equal(objectsInSF.length, 1); + assert.equal(objectsInSF[0].get('name'), 'caltrain'); + done(); + }) + .catch(done.fail); }); - it('can swap latitude', (done) => { + it('can swap latitude', done => { const caltrainStationLocation = new Parse.GeoPoint(37.776346, -122.394218); const caltrainStation = new Parse.Object('Location'); caltrainStation.set('location', caltrainStationLocation); @@ -98,14 +107,17 @@ describe('Geo Box', () => { santaClara.set('location', santaClaraLocation); santaClara.set('name', 'santa clara'); - Parse.Object.saveAll([caltrainStation, santaClara]).then(() => { - const query = new Parse.Query('Location'); - query.withinGeoBox('location', southwestOfSF, northeastOfSF); - return query.find(); - }).then((objectsInSF) => { - assert.equal(objectsInSF.length, 1); - assert.equal(objectsInSF[0].get('name'), 'caltrain'); - done(); - }).catch(done.fail); + Parse.Object.saveAll([caltrainStation, santaClara]) + .then(() => { + const query = new Parse.Query('Location'); + query.withinGeoBox('location', southwestOfSF, northeastOfSF); + return query.find(); + }) + .then(objectsInSF => { + assert.equal(objectsInSF.length, 1); + assert.equal(objectsInSF[0].get('name'), 'caltrain'); + done(); + }) + .catch(done.fail); }); }); diff --git a/integration/test/ParseGeoPointTest.js b/integration/test/ParseGeoPointTest.js index cb34aad69..ab194fbf4 100644 --- a/integration/test/ParseGeoPointTest.js +++ b/integration/test/ParseGeoPointTest.js @@ -9,57 +9,73 @@ const TestPoint = Parse.Object.extend('TestPoint'); const Container = Parse.Object.extend('Container'); describe('Geo Point', () => { - beforeAll((done) => { + beforeAll(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.CoreManager.set('REQUEST_ATTEMPT_LIMIT', 1); Parse.Storage._clear(); - clear().then(() => { - const sacramento = new TestPoint(); - sacramento.set('location', new Parse.GeoPoint(38.52, -121.50)); - sacramento.set('name', 'Sacramento'); - - const honolulu = new TestPoint(); - honolulu.set('location', new Parse.GeoPoint(21.35, -157.93)); - honolulu.set('name', 'Honolulu'); - - const sf = new TestPoint(); - sf.set('location', new Parse.GeoPoint(37.75, -122.68)); - sf.set('name', 'San Francisco'); - - return Parse.Object.saveAll([sacramento, honolulu, sf]); - }).then(() => { - return Parse.User.logOut(); - }).then(() => { done() }, () => { done() }); + clear() + .then(() => { + const sacramento = new TestPoint(); + sacramento.set('location', new Parse.GeoPoint(38.52, -121.5)); + sacramento.set('name', 'Sacramento'); + + const honolulu = new TestPoint(); + honolulu.set('location', new Parse.GeoPoint(21.35, -157.93)); + honolulu.set('name', 'Honolulu'); + + const sf = new TestPoint(); + sf.set('location', new Parse.GeoPoint(37.75, -122.68)); + sf.set('name', 'San Francisco'); + + return Parse.Object.saveAll([sacramento, honolulu, sf]); + }) + .then(() => { + return Parse.User.logOut(); + }) + .then( + () => { + done(); + }, + () => { + done(); + } + ); }); - it('can save geo points', (done) => { + it('can save geo points', done => { const point = new Parse.GeoPoint(44.0, -11.0); const obj = new TestObject(); - obj.set('location', point) + obj.set('location', point); obj.set('name', 'Ferndale'); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert(o.get('location')); - assert.equal(o.get('location').latitude, 44.0); - assert.equal(o.get('location').longitude, -11.0); - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert(o.get('location')); + assert.equal(o.get('location').latitude, 44.0); + assert.equal(o.get('location').longitude, -11.0); + done(); + }); }); - it('can only store one geo point per object', (done) => { + it('can only store one geo point per object', done => { const point = new Parse.GeoPoint(20, 20); const obj = new Container(); obj.set('locationOne', point); obj.set('locationTwo', point); - obj.save().then(done.fail).catch(() => { - done(); - }); + obj + .save() + .then(done.fail) + .catch(() => { + done(); + }); }); - it('can sequence a line of points by distance - without unsorted parameter', (done) => { + it('can sequence a line of points by distance - without unsorted parameter', done => { const line = []; for (let i = 0; i < 10; i++) { const obj = new TestObject(); @@ -69,21 +85,23 @@ describe('Geo Point', () => { obj.set('seq', i); line.push(obj); } - Parse.Object.saveAll(line).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(24, 19); - query.equalTo('construct', 'line'); - query.withinMiles('location', point, 10000); - return query.find(); - }).then((results) => { - assert.equal(results.length, 10); - assert.equal(results[0].get('seq'), 9); - assert.equal(results[3].get('seq'), 6); - done(); - }); + Parse.Object.saveAll(line) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(24, 19); + query.equalTo('construct', 'line'); + query.withinMiles('location', point, 10000); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 10); + assert.equal(results[0].get('seq'), 9); + assert.equal(results[3].get('seq'), 6); + done(); + }); }); - it('can sequence a line of points by distance - with unsorted parameter', (done) => { + it('can sequence a line of points by distance - with unsorted parameter', done => { const line = []; for (let i = 0; i < 10; i++) { const obj = new TestObject(); @@ -93,104 +111,112 @@ describe('Geo Point', () => { obj.set('seq', i); line.push(obj); } - Parse.Object.saveAll(line).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(24, 19); - query.equalTo('construct', 'line_unsorted'); - query.withinMiles('location', point, 10000, true); - return query.find(); - }).then((results) => { - assert.equal(results.length, 10); - assert.equal(results[0].get('seq'), 9); - assert.equal(results[3].get('seq'), 6); - done(); - }); + Parse.Object.saveAll(line) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(24, 19); + query.equalTo('construct', 'line_unsorted'); + query.withinMiles('location', point, 10000, true); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 10); + assert.equal(results[0].get('seq'), 9); + assert.equal(results[3].get('seq'), 6); + done(); + }); }); - it('can query within large distances', (done) => { + it('can query within large distances', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); const point = new Parse.GeoPoint(0, i * 45); obj.set('location', point); - obj.set('construct', 'large_dist') + obj.set('construct', 'large_dist'); obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'large_dist'); - query.withinRadians('location', point, 3.14); - return query.find(); - }).then((results) => { - assert.equal(results.length, 3); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'large_dist'); + query.withinRadians('location', point, 3.14); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 3); + done(); + }); }); - it('can query within medium distances', (done) => { + it('can query within medium distances', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); const point = new Parse.GeoPoint(0, i * 45); obj.set('location', point); - obj.set('construct', 'medium_dist') + obj.set('construct', 'medium_dist'); obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'medium_dist'); - query.withinRadians('location', point, 3.14 * 0.5); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].get('index'), 0); - assert.equal(results[1].get('index'), 1); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'medium_dist'); + query.withinRadians('location', point, 3.14 * 0.5); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].get('index'), 0); + assert.equal(results[1].get('index'), 1); + done(); + }); }); - it('can query within small distances', (done) => { + it('can query within small distances', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); const point = new Parse.GeoPoint(0, i * 45); obj.set('location', point); - obj.set('construct', 'small_dist') + obj.set('construct', 'small_dist'); obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'small_dist'); - query.withinRadians('location', point, 3.14 * 0.25); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('index'), 0); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'small_dist'); + query.withinRadians('location', point, 3.14 * 0.25); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('index'), 0); + done(); + }); }); - it('can measure distance within km - everywhere', (done) => { + it('can measure distance within km - everywhere', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 4000.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 3); done(); }); }); - it('can measure distance within km - california', (done) => { + it('can measure distance within km - california', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 3700.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); assert.equal(results[0].get('name'), 'San Francisco'); assert.equal(results[1].get('name'), 'Sacramento'); @@ -198,42 +224,42 @@ describe('Geo Point', () => { }); }); - it('can measure distance within km - bay area', (done) => { + it('can measure distance within km - bay area', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 100.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); assert.equal(results[0].get('name'), 'San Francisco'); done(); }); }); - it('can measure distance within km - mid peninsula', (done) => { + it('can measure distance within km - mid peninsula', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 10.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('can measure distance within miles - everywhere', (done) => { + it('can measure distance within miles - everywhere', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 2500.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 3); done(); }); }); - it('can measure distance within miles - california', (done) => { + it('can measure distance within miles - california', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 2200.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); assert.equal(results[0].get('name'), 'San Francisco'); assert.equal(results[1].get('name'), 'Sacramento'); @@ -241,28 +267,28 @@ describe('Geo Point', () => { }); }); - it('can measure distance within miles - bay area', (done) => { + it('can measure distance within miles - bay area', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 75.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); assert.equal(results[0].get('name'), 'San Francisco'); done(); }); }); - it('can measure distance within miles - mid peninsula', (done) => { + it('can measure distance within miles - mid peninsula', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 10.0); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('can query within large distances unsorted', (done) => { + it('can query within large distances unsorted', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); @@ -272,19 +298,21 @@ describe('Geo Point', () => { obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'large_dist_unsorted'); - query.withinRadians('location', point, 3.14, false); - return query.find(); - }).then((results) => { - assert.equal(results.length, 3); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'large_dist_unsorted'); + query.withinRadians('location', point, 3.14, false); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 3); + done(); + }); }); - it('can query within medium distances unsorted', (done) => { + it('can query within medium distances unsorted', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); @@ -294,21 +322,23 @@ describe('Geo Point', () => { obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'medium_dist_unsorted'); - query.withinRadians('location', point, 3.14 * 0.5, false); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].get('index'), 0); - assert.equal(results[1].get('index'), 1); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'medium_dist_unsorted'); + query.withinRadians('location', point, 3.14 * 0.5, false); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].get('index'), 0); + assert.equal(results[1].get('index'), 1); + done(); + }); }); - it('can query within small distances unsorted', (done) => { + it('can query within small distances unsorted', done => { const objects = []; for (let i = 0; i < 3; i++) { const obj = new TestObject(); @@ -318,34 +348,36 @@ describe('Geo Point', () => { obj.set('index', i); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - const point = new Parse.GeoPoint(1, -1); - query.equalTo('construct', 'small_dist_unsorted'); - query.withinRadians('location', point, 3.14 * 0.25, false); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('index'), 0); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + const point = new Parse.GeoPoint(1, -1); + query.equalTo('construct', 'small_dist_unsorted'); + query.withinRadians('location', point, 3.14 * 0.25, false); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('index'), 0); + done(); + }); }); - it('can measure distance within km unsorted - everywhere', (done) => { + it('can measure distance within km unsorted - everywhere', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 4000.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 3); done(); }); }); - it('can measure distance within km unsorted - california', (done) => { + it('can measure distance within km unsorted - california', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 3700.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); assert.equal(results[0].get('name'), 'San Francisco'); assert.equal(results[1].get('name'), 'Sacramento'); @@ -353,42 +385,42 @@ describe('Geo Point', () => { }); }); - it('can measure distance within km unsorted - bay area', (done) => { + it('can measure distance within km unsorted - bay area', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 100.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); assert.equal(results[0].get('name'), 'San Francisco'); done(); }); }); - it('can measure distance within km unsorted - mid peninsula', (done) => { + it('can measure distance within km unsorted - mid peninsula', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinKilometers('location', sfo, 10.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('can measure distance within miles unsorted - everywhere', (done) => { + it('can measure distance within miles unsorted - everywhere', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 2500.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 3); done(); }); }); - it('can measure distance within miles unsorted - california', (done) => { + it('can measure distance within miles unsorted - california', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 2200.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); assert.equal(results[0].get('name'), 'San Francisco'); assert.equal(results[1].get('name'), 'Sacramento'); @@ -396,82 +428,88 @@ describe('Geo Point', () => { }); }); - it('can measure distance within miles unsorted - bay area', (done) => { + it('can measure distance within miles unsorted - bay area', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 75.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); assert.equal(results[0].get('name'), 'San Francisco'); done(); }); }); - it('can measure distance within miles unsorted - mid peninsula', (done) => { + it('can measure distance within miles unsorted - mid peninsula', done => { const sfo = new Parse.GeoPoint(37.6189722, -122.3748889); const query = new Parse.Query(TestPoint); query.withinMiles('location', sfo, 10.0, false); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('supports withinPolygon open path', (done) => { + it('supports withinPolygon open path', done => { const points = [ new Parse.GeoPoint(37.85, -122.33), - new Parse.GeoPoint(37.85, -122.90), - new Parse.GeoPoint(37.68, -122.90), - new Parse.GeoPoint(37.68, -122.33) + new Parse.GeoPoint(37.85, -122.9), + new Parse.GeoPoint(37.68, -122.9), + new Parse.GeoPoint(37.68, -122.33), ]; const query = new Parse.Query(TestPoint); query.withinPolygon('location', points); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); done(); }); }); - it('supports withinPolygon closed path', (done) => { + it('supports withinPolygon closed path', done => { const points = [ - new Parse.GeoPoint(38.52, -121.50), + new Parse.GeoPoint(38.52, -121.5), new Parse.GeoPoint(37.75, -157.93), new Parse.GeoPoint(37.578072, -121.379914), - new Parse.GeoPoint(38.52, -121.50) + new Parse.GeoPoint(38.52, -121.5), ]; const query = new Parse.Query(TestPoint); query.withinPolygon('location', points); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); done(); }); }); - it('non array withinPolygon', (done) => { + it('non array withinPolygon', done => { const query = new Parse.Query(TestPoint); query.withinPolygon('location', 1234); - query.find().catch((err) => { + query.find().catch(err => { assert.equal(err.code, Parse.Error.INVALID_JSON); done(); }); }); - it('invalid array withinPolygon', (done) => { + it('invalid array withinPolygon', done => { const query = new Parse.Query(TestPoint); query.withinPolygon('location', [1234]); - query.find().catch((err) => { + query.find().catch(err => { assert.equal(err.code, Parse.Error.INVALID_JSON); done(); }); }); - xit('minimum 3 points withinPolygon', function(done) { - const query = new Parse.Query(TestPoint); - query.withinPolygon('location', []); - query.find().then(done.fail, (err) => { - assert.equal(err.code, Parse.Error.INVALID_JSON); - done(); - }) - .catch(done.fail); - }, 'Test passes locally but not on CI'); + xit( + 'minimum 3 points withinPolygon', + function (done) { + const query = new Parse.Query(TestPoint); + query.withinPolygon('location', []); + query + .find() + .then(done.fail, err => { + assert.equal(err.code, Parse.Error.INVALID_JSON); + done(); + }) + .catch(done.fail); + }, + 'Test passes locally but not on CI' + ); }); diff --git a/integration/test/ParseLiveQueryTest.js b/integration/test/ParseLiveQueryTest.js index 8fa5eb06d..89e33a0b0 100644 --- a/integration/test/ParseLiveQueryTest.js +++ b/integration/test/ParseLiveQueryTest.js @@ -9,7 +9,7 @@ const TestObject = Parse.Object.extend('TestObject'); const DiffObject = Parse.Object.extend('DiffObject'); describe('Parse LiveQuery', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.User.enableUnsafeCurrentUser(); @@ -17,7 +17,7 @@ describe('Parse LiveQuery', () => { clear().then(done).catch(done.fail); }); - it('can subscribe to query', async (done) => { + it('can subscribe to query', async done => { const object = new TestObject(); await object.save(); const installationId = await Parse.CoreManager.getInstallationController().currentInstallationId(); @@ -30,12 +30,12 @@ describe('Parse LiveQuery', () => { assert.equal(object.get('foo'), 'bar'); assert.equal(response.installationId, installationId); done(); - }) + }); object.set({ foo: 'bar' }); await object.save(); }); - it('can subscribe to query with client', async (done) => { + it('can subscribe to query with client', async done => { const object = new TestObject(); await object.save(); const installationId = await Parse.CoreManager.getInstallationController().currentInstallationId(); @@ -73,11 +73,11 @@ describe('Parse LiveQuery', () => { subscriptionA.on('update', object => { count++; assert.equal(object.get('foo'), 'bar'); - }) + }); subscriptionB.on('update', object => { count++; assert.equal(object.get('foo'), 'baz'); - }) + }); await objectA.save({ foo: 'bar' }); await objectB.save({ foo: 'baz' }); await sleep(1000); @@ -99,11 +99,11 @@ describe('Parse LiveQuery', () => { subscriptionA.on('update', object => { count++; assert.equal(object.get('foo'), 'bar'); - }) + }); subscriptionB.on('update', object => { count++; assert.equal(object.get('foo'), 'baz'); - }) + }); await objectA.save({ foo: 'bar' }); await objectB.save({ foo: 'baz' }); await sleep(1000); @@ -124,11 +124,11 @@ describe('Parse LiveQuery', () => { let count = 0; subscriptionA.on('update', () => { count++; - }) + }); subscriptionB.on('update', object => { count++; assert.equal(object.get('foo'), 'baz'); - }) + }); subscriptionA.unsubscribe(); await objectA.save({ foo: 'bar' }); await objectB.save({ foo: 'baz' }); @@ -150,11 +150,11 @@ describe('Parse LiveQuery', () => { let count = 0; subscriptionA.on('update', () => { count++; - }) + }); subscriptionB.on('update', object => { count++; assert.equal(object.get('foo'), 'baz'); - }) + }); await subscriptionA.unsubscribe(); await objectA.save({ foo: 'bar' }); await objectB.save({ foo: 'baz' }); @@ -162,7 +162,7 @@ describe('Parse LiveQuery', () => { assert.equal(count, 1); }); - it('can subscribe to ACL', async (done) => { + it('can subscribe to ACL', async done => { const user = await Parse.User.signUp('ooo', 'password'); const ACL = new Parse.ACL(user); @@ -173,15 +173,15 @@ describe('Parse LiveQuery', () => { const query = new Parse.Query(TestObject); query.equalTo('objectId', object.id); const subscription = await query.subscribe(user.getSessionToken()); - subscription.on('update', async (object) => { + subscription.on('update', async object => { assert.equal(object.get('foo'), 'bar'); await Parse.User.logOut(); done(); - }) + }); await object.save({ foo: 'bar' }); }); - it('can subscribe to null sessionToken', async (done) => { + it('can subscribe to null sessionToken', async done => { const user = await Parse.User.signUp('oooooo', 'password'); const readOnly = Parse.User.readOnlyAttributes(); @@ -195,18 +195,18 @@ describe('Parse LiveQuery', () => { const query = new Parse.Query(TestObject); query.equalTo('objectId', object.id); const subscription = await query.subscribe(); - subscription.on('update', async (object) => { + subscription.on('update', async object => { assert.equal(object.get('foo'), 'bar'); - Parse.User.readOnlyAttributes = function() { + Parse.User.readOnlyAttributes = function () { return readOnly; }; await Parse.User.logOut(); done(); - }) + }); await object.save({ foo: 'bar' }); }); - it('can subscribe with open event', async (done) => { + it('can subscribe with open event', async done => { const installationId = await Parse.CoreManager.getInstallationController().currentInstallationId(); const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); const object = new TestObject(); @@ -215,14 +215,14 @@ describe('Parse LiveQuery', () => { const query = new Parse.Query(TestObject); query.equalTo('objectId', object.id); const subscription = await query.subscribe(); - subscription.on('open', (response) => { + subscription.on('open', response => { assert.equal(response.clientId, client.id); assert.equal(response.installationId, installationId); done(); - }) + }); }); - it('can subscribe to query with fields', async (done) => { + it('can subscribe to query with fields', async done => { const object = new TestObject(); await object.save({ name: 'hello', age: 21 }); @@ -231,12 +231,12 @@ describe('Parse LiveQuery', () => { query.select(['name']); const subscription = await query.subscribe(); - subscription.on('update', (object) => { + subscription.on('update', object => { assert.equal(object.get('name'), 'hello'); - assert.equal(object.get('age'), undefined) + assert.equal(object.get('age'), undefined); assert.equal(object.get('foo'), undefined); done(); - }) + }); object.set({ foo: 'bar' }); await object.save(); }); diff --git a/integration/test/ParseLocalDatastoreTest.js b/integration/test/ParseLocalDatastoreTest.js index ecfa9572a..aa291c72d 100644 --- a/integration/test/ParseLocalDatastoreTest.js +++ b/integration/test/ParseLocalDatastoreTest.js @@ -169,7 +169,7 @@ function runTest(controller) { user.set('field', 'test'); user.setPassword('asdf'); user.setUsername('zxcv'); - await user.signUp() + await user.signUp(); await user.pin(); const json = user._toFullJSON(); @@ -331,7 +331,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -340,7 +344,11 @@ function runTest(controller) { localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [obj2._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); @@ -356,7 +364,11 @@ function runTest(controller) { await Parse.Object.pinAllWithName('test_pin', objects); const localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_pin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [obj1._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [obj2._toFullJSON()]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [obj3._toFullJSON()]); @@ -633,7 +645,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -663,7 +679,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -687,7 +707,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert(Object.keys(localDatastore).length === 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -719,7 +743,11 @@ function runTest(controller) { let localDatastore = await Parse.LocalDatastore._getAllContents(); assert.equal(Object.keys(localDatastore).length, 4); - assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [LDS_KEY(obj1), LDS_KEY(obj2), LDS_KEY(obj3)]); + assert.deepEqual(localDatastore[PIN_PREFIX + 'test_unpin'], [ + LDS_KEY(obj1), + LDS_KEY(obj2), + LDS_KEY(obj3), + ]); assert.deepEqual(localDatastore[LDS_KEY(obj1)], [LDS_FULL_JSON(obj1)]); assert.deepEqual(localDatastore[LDS_KEY(obj2)], [LDS_FULL_JSON(obj2)]); assert.deepEqual(localDatastore[LDS_KEY(obj3)], [LDS_FULL_JSON(obj3)]); @@ -865,11 +893,11 @@ function runTest(controller) { }); it(`${controller.name} can fetchFromLocalDatastore break multiple cycle`, async () => { - const A = new TestObject({ value: 'A'}); - const B = new TestObject({ value: 'B'}); - const C = new TestObject({ value: 'C'}); - const D = new TestObject({ value: 'D'}); - const E = new TestObject({ value: 'E'}); + const A = new TestObject({ value: 'A' }); + const B = new TestObject({ value: 'B' }); + const C = new TestObject({ value: 'C' }); + const D = new TestObject({ value: 'D' }); + const E = new TestObject({ value: 'E' }); await Parse.Object.saveAll([A, B, C, D, E]); /* @@ -1149,9 +1177,9 @@ function runTest(controller) { it('can do containedBy queries with numbers', async () => { const objects = [ - new TestObject({ containedBy:true, numbers: [0, 1, 2] }), - new TestObject({ containedBy:true, numbers: [2, 0] }), - new TestObject({ containedBy:true, numbers: [1, 2, 3, 4] }), + new TestObject({ containedBy: true, numbers: [0, 1, 2] }), + new TestObject({ containedBy: true, numbers: [2, 0] }), + new TestObject({ containedBy: true, numbers: [1, 2, 3, 4] }), ]; await Parse.Object.saveAll(objects); @@ -1166,7 +1194,7 @@ function runTest(controller) { }); it('can do containedBy queries with pointer', async () => { - const objects = Array.from(Array(10).keys()).map((idx) => { + const objects = Array.from(Array(10).keys()).map(idx => { const obj = new Parse.Object('Object'); obj.set('key', idx); return obj; @@ -1269,7 +1297,7 @@ function runTest(controller) { it(`${controller.name} can perform containedIn queries`, async () => { const query = new Parse.Query('BoxedNumber'); - query.containedIn('number', [3,5,7,9,11]); + query.containedIn('number', [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 4); @@ -1277,7 +1305,7 @@ function runTest(controller) { it(`${controller.name} can perform notContainedIn queries`, async () => { const query = new Parse.Query('BoxedNumber'); - query.notContainedIn('number', [3,5,7,9,11]); + query.notContainedIn('number', [3, 5, 7, 9, 11]); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 6); @@ -1352,7 +1380,7 @@ function runTest(controller) { try { await query.get(undefined); assert.equal(false, true); - } catch(e) { + } catch (e) { assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); } }); @@ -1374,7 +1402,7 @@ function runTest(controller) { }); it(`${controller.name} can query for the first with two results`, async () => { - const objects = [new TestObject({x: 44}), new TestObject({x: 44})]; + const objects = [new TestObject({ x: 44 }), new TestObject({ x: 44 })]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); const query = new Parse.Query(TestObject); @@ -1400,8 +1428,14 @@ function runTest(controller) { it(`${controller.name} can test object inequality`, async () => { const item1 = new TestObject(); const item2 = new TestObject(); - const container1 = new Parse.Object({className: 'CoolContainer', item: item1}); - const container2 = new Parse.Object({className: 'CoolContainer', item: item2}); + const container1 = new Parse.Object({ + className: 'CoolContainer', + item: item1, + }); + const container2 = new Parse.Object({ + className: 'CoolContainer', + item: item2, + }); const objects = [item1, item2, container1, container2]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); @@ -1440,7 +1474,7 @@ function runTest(controller) { await Parse.Object.saveAll([ new TestObject({ skipCount: true }), new TestObject({ skipCount: true }), - new TestObject({ skipCount: true }) + new TestObject({ skipCount: true }), ]); let query = new Parse.Query(TestObject); query.equalTo('skipCount', true); @@ -1467,7 +1501,7 @@ function runTest(controller) { const query = new Parse.Query('BoxedNumber'); query.greaterThan('number', 1); query.fromLocalDatastore(); - const count = await query.count() + const count = await query.count(); assert.equal(count, 8); }); @@ -1618,7 +1652,6 @@ function runTest(controller) { assert.equal(results[3].get('string'), 'b'); }); - it(`${controller.name} can not order by password`, async () => { const query = new Parse.Query('BoxedNumber'); query.ascending('_password'); @@ -1632,10 +1665,22 @@ function runTest(controller) { }); it(`${controller.name} can order by _created_at`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - const obj4 = await new Parse.Object({className: 'TestObject', orderedDate: true}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + const obj4 = await new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); @@ -1651,10 +1696,22 @@ function runTest(controller) { }); it(`${controller.name} can order by createdAt`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - const obj4 = await new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + const obj4 = await new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); @@ -1670,10 +1727,22 @@ function runTest(controller) { }); it(`${controller.name} can order by _updated_at`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - const obj4 = await new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + const obj4 = await new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); @@ -1689,10 +1758,22 @@ function runTest(controller) { }); it(`${controller.name} can order by updatedAt`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - const obj4 = await new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + const obj4 = await new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); @@ -1708,10 +1789,26 @@ function runTest(controller) { }); it(`${controller.name} can test time equality`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', timed: true, name: 'item2'}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', timed: true, name: 'item1'}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', timed: true, name: 'item3'}).save(); - const last = await new Parse.Object({className: 'TestObject', timed: true, name: 'item4'}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item2', + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item1', + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item3', + }).save(); + const last = await new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item4', + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, last]); @@ -1726,10 +1823,26 @@ function runTest(controller) { }); it(`${controller.name} can test time inequality`, async () => { - const obj1 = await new Parse.Object({className: 'TestObject', timed2: true, name: 'item1'}).save(); - const obj2 = await new Parse.Object({className: 'TestObject', timed2: true, name: 'item2'}).save(); - const obj3 = await new Parse.Object({className: 'TestObject', timed2: true, name: 'item3'}).save(); - const obj4 = await new Parse.Object({className: 'TestObject', timed2: true, name: 'item4'}).save(); + const obj1 = await new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item1', + }).save(); + const obj2 = await new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item2', + }).save(); + const obj3 = await new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item3', + }).save(); + const obj4 = await new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item4', + }).save(); await Parse.Object.pinAll([obj1, obj2, obj3, obj4]); @@ -1808,7 +1921,7 @@ function runTest(controller) { await obj.pin(); const query = new Parse.Query(TestObject); - query.matches('website',/parse\.com/,'mixs'); + query.matches('website', /parse\.com/, 'mixs'); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); @@ -1821,20 +1934,21 @@ function runTest(controller) { await obj.pin(); const query = new Parse.Query(TestObject); - query.matches('website', /parse\.com/mi); + query.matches('website', /parse\.com/im); query.fromLocalDatastore(); const results = await query.find(); assert.equal(results.length, 1); }); it(`${controller.name} can test contains`, async () => { - const someAscii = "\\E' !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU" + - "VWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'"; + const someAscii = + "\\E' !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU" + + "VWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'"; const objects = [ - new TestObject({contains: true, myString: 'zax' + someAscii + 'qub'}), - new TestObject({contains: true, myString: 'start' + someAscii}), - new TestObject({contains: true, myString: someAscii + 'end'}), - new TestObject({contains: true, myString: someAscii}) + new TestObject({ contains: true, myString: 'zax' + someAscii + 'qub' }), + new TestObject({ contains: true, myString: 'start' + someAscii }), + new TestObject({ contains: true, myString: someAscii + 'end' }), + new TestObject({ contains: true, myString: someAscii }), ]; await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); @@ -1906,7 +2020,9 @@ function runTest(controller) { it(`${controller.name} can test if a relation exists`, async () => { const objects = []; for (let i = 0; i < 10; i++) { - const container = new Parse.Object('Container', { relation_exists: true }); + const container = new Parse.Object('Container', { + relation_exists: true, + }); if (i % 2) { container.set('y', i); } else { @@ -2039,7 +2155,7 @@ function runTest(controller) { query.equalTo('objectId', parent.id); query.includeAll(); query.fromLocalDatastore(); - await query.each((obj) => { + await query.each(obj => { assert.equal(obj.get('child1').get('foo'), 'bar'); assert.equal(obj.get('child2').get('foo'), 'baz'); assert.equal(obj.get('child3').get('foo'), 'bin'); @@ -2080,7 +2196,7 @@ function runTest(controller) { parent: new Parent({ y: i, child: new Child({ - x: i + x: i, }), }), }); @@ -2098,7 +2214,7 @@ function runTest(controller) { const results = await q.find(); assert.equal(results.length, 5); - results.forEach((o) => { + results.forEach(o => { assert.equal(o.get('z'), o.get('parent').get('y')); assert.equal(o.get('z'), o.get('parent').get('child').get('x')); }); @@ -2134,7 +2250,7 @@ function runTest(controller) { let ChildObject = Parse.Object.extend('ChildObject', { foo() { return 'foo'; - } + }, }); const parent = new ParentObject(); @@ -2145,7 +2261,7 @@ function runTest(controller) { ChildObject = Parse.Object.extend('ChildObject', { bar() { return 'bar'; - } + }, }); const query = new Parse.Query(ParentObject); @@ -2166,10 +2282,12 @@ function runTest(controller) { const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { - objects.push(new ParentObject({ - child: new ChildObject({x: i, qtest: true}), - x: 10 + i, - })); + objects.push( + new ParentObject({ + child: new ChildObject({ x: i, qtest: true }), + x: 10 + i, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); @@ -2183,7 +2301,7 @@ function runTest(controller) { const results = await q.find(); assert.equal(results.length, 4); - results.forEach((o) => { + results.forEach(o => { assert(o.get('x') > 15); }); }); @@ -2193,11 +2311,13 @@ function runTest(controller) { const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { - objects.push(new ParentObject({ - child: new ChildObject({x: i, dneqtest: true}), - dneqtest: true, - x: 10 + i, - })); + objects.push( + new ParentObject({ + child: new ChildObject({ x: i, dneqtest: true }), + dneqtest: true, + x: 10 + i, + }) + ); } await Parse.Object.saveAll(objects); await Parse.Object.pinAll(objects); @@ -2212,7 +2332,7 @@ function runTest(controller) { const results = await q.find(); assert.equal(results.length, 6); - results.forEach((o) => { + results.forEach(o => { assert(o.get('x') >= 10); assert(o.get('x') <= 15); }); @@ -2286,7 +2406,9 @@ function runTest(controller) { assert.equal(objAgain.get('owner').get('age'), 21); try { await Parse.User.logOut(); - } catch(e) { /* */ } + } catch (e) { + /* */ + } }); it(`${controller.name} can build OR queries`, async () => { @@ -2311,7 +2433,7 @@ function runTest(controller) { orQuery.fromLocalDatastore(); const results = await orQuery.find(); assert.equal(results.length, 6); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') < 2 || number.get('x') > 5); }); }); @@ -2344,7 +2466,7 @@ function runTest(controller) { const orQuery = Parse.Query.or(q1, q2); orQuery.fromLocalDatastore(); - const results = await orQuery.find(); + const results = await orQuery.find(); assert.equal(results.length, 3); }); @@ -2370,7 +2492,7 @@ function runTest(controller) { andQuery.fromLocalDatastore(); const results = await andQuery.find(); assert.equal(results.length, 2); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') > 2 && number.get('x') < 5); }); }); @@ -2426,7 +2548,7 @@ function runTest(controller) { const results = await norQuery.find(); assert.equal(results.length, 3); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') >= 3 && number.get('x') <= 5); }); }); @@ -2455,7 +2577,7 @@ function runTest(controller) { const results = await norQuery.find(); assert.equal(results.length, 8); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') !== 4 || number.get('x') !== 5); }); }); @@ -2473,7 +2595,7 @@ function runTest(controller) { query.equalTo('eachtest', true); query.lessThan('x', 25); query.fromLocalDatastore(); - await query.each((obj) => { + await query.each(obj => { seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); assert.equal(seen.length, 25); @@ -2497,7 +2619,7 @@ function runTest(controller) { query.ascending('x'); query.fromLocalDatastore(); try { - await query.each((obj) => { + await query.each(obj => { seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { @@ -2520,7 +2642,7 @@ function runTest(controller) { query.limit(20); query.fromLocalDatastore(); try { - await query.each((obj) => { + await query.each(obj => { seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { @@ -2543,7 +2665,7 @@ function runTest(controller) { query.skip(20); query.fromLocalDatastore(); try { - await query.each((obj) => { + await query.each(obj => { seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; }); } catch (e) { @@ -2579,7 +2701,7 @@ function runTest(controller) { q.equalTo('objectId', obj.id); q.select('foo'); q.fromLocalDatastore(); - await q.each((o) => { + await q.each(o => { assert(o.id); assert.equal(o.get('foo'), 'baz'); assert.equal(o.get('bar'), undefined); @@ -2627,7 +2749,7 @@ function runTest(controller) { it(`${controller.name} supports withinPolygon`, async () => { const sacramento = new TestObject(); - sacramento.set('location', new Parse.GeoPoint(38.52, -121.50)); + sacramento.set('location', new Parse.GeoPoint(38.52, -121.5)); sacramento.set('name', 'Sacramento'); const honolulu = new TestObject(); @@ -2643,9 +2765,9 @@ function runTest(controller) { const points = [ new Parse.GeoPoint(37.85, -122.33), - new Parse.GeoPoint(37.85, -122.90), - new Parse.GeoPoint(37.68, -122.90), - new Parse.GeoPoint(37.68, -122.33) + new Parse.GeoPoint(37.85, -122.9), + new Parse.GeoPoint(37.68, -122.9), + new Parse.GeoPoint(37.68, -122.33), ]; const query = new Parse.Query(TestObject); query.withinPolygon('location', points); @@ -2655,9 +2777,25 @@ function runTest(controller) { }); it(`${controller.name} supports polygonContains`, async () => { - const p1 = [[0,0], [0,1], [1,1], [1,0]]; - const p2 = [[0,0], [0,2], [2,2], [2,0]]; - const p3 = [[10,10], [10,15], [15,15], [15,10], [10,10]]; + const p1 = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const p2 = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; + const p3 = [ + [10, 10], + [10, 15], + [15, 15], + [15, 10], + [10, 10], + ]; const polygon1 = new Parse.Polygon(p1); const polygon2 = new Parse.Polygon(p2); @@ -2683,8 +2821,12 @@ function runTest(controller) { constructor() { super('ClassA'); } - get name() { return this.get('name'); } - set name(value) { this.set('name', value); } + get name() { + return this.get('name'); + } + set name(value) { + this.set('name', value); + } } Parse.Object.registerSubclass('ClassA', ClassA); @@ -2692,11 +2834,19 @@ function runTest(controller) { constructor() { super('ClassB'); } - get name() { return this.get('name'); } - set name(value) { this.set('name', value); } + get name() { + return this.get('name'); + } + set name(value) { + this.set('name', value); + } - get classA() { return this.get('classA'); } - set classA(value) { this.set('classA', value); } + get classA() { + return this.get('classA'); + } + set classA(value) { + this.set('classA', value); + } } Parse.Object.registerSubclass('ClassB', ClassB); @@ -2729,7 +2879,7 @@ function runTest(controller) { } describe('Parse LocalDatastore', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.CoreManager.getInstallationController()._setInstallationIdCache('1234'); @@ -2737,13 +2887,16 @@ describe('Parse LocalDatastore', () => { Parse.User.enableUnsafeCurrentUser(); Parse.Storage._clear(); clear().then(() => { - done() + done(); }); }); const controllers = [ { name: 'Default', file: '../../lib/node/LocalDatastoreController' }, - { name: 'React-Native', file: '../../lib/node/LocalDatastoreController.react-native' }, + { + name: 'React-Native', + file: '../../lib/node/LocalDatastoreController.react-native', + }, ]; for (let i = 0; i < controllers.length; i += 1) { diff --git a/integration/test/ParseMasterKeyTest.js b/integration/test/ParseMasterKeyTest.js index aedbcfcde..2867d541a 100644 --- a/integration/test/ParseMasterKeyTest.js +++ b/integration/test/ParseMasterKeyTest.js @@ -7,7 +7,7 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Master Key', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); @@ -16,7 +16,7 @@ describe('Master Key', () => { }); }); - it('can perform a simple save', (done) => { + it('can perform a simple save', done => { const object = new TestObject(); object.set('color', 'purple'); object.save(null, { useMasterKey: true }).then(() => { @@ -25,21 +25,25 @@ describe('Master Key', () => { }); }); - it('can perform a save without permissions', (done) => { + it('can perform a save without permissions', done => { let object; - Parse.User.signUp('andrew', 'password').then((user) => { - object = new TestObject({ ACL: new Parse.ACL(user) }); - return object.save(); - }).then(() => { - Parse.User.logOut(); - return object.save(null, { useMasterKey: true }); - }).then(() => { - // expect success - done(); - }).catch((e) => console.log(e)); + Parse.User.signUp('andrew', 'password') + .then(user => { + object = new TestObject({ ACL: new Parse.ACL(user) }); + return object.save(); + }) + .then(() => { + Parse.User.logOut(); + return object.save(null, { useMasterKey: true }); + }) + .then(() => { + // expect success + done(); + }) + .catch(e => console.log(e)); }); - it('throws when no master key is provided', (done) => { + it('throws when no master key is provided', done => { Parse.CoreManager.set('MASTER_KEY', null); const object = new TestObject(); object.save(null, { useMasterKey: true }).catch(() => { diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 03072ba1e..777b1d5cb 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -9,7 +9,7 @@ const Item = Parse.Object.extend('Item'); const Container = Parse.Object.extend('Container'); describe('Parse Object', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); @@ -18,9 +18,9 @@ describe('Parse Object', () => { }); }); - it('can create objects', (done) => { + it('can create objects', done => { const object = new TestObject({ test: 'test' }); - object.save().then((o) => { + object.save().then(o => { assert(o); assert(o.id); assert.equal(o.get('test'), 'test'); @@ -28,56 +28,68 @@ describe('Parse Object', () => { }); }); - it('can update objects', (done) => { + it('can update objects', done => { const object = new TestObject({ test: 'test' }); - object.save().then((o) => { - const o2 = new TestObject({ objectId: o.id }); - o2.set('test', 'changed'); - return o2.save(); - }).then((o) => { - assert.equal(o.get('test'), 'changed'); - done(); - }); + object + .save() + .then(o => { + const o2 = new TestObject({ objectId: o.id }); + o2.set('test', 'changed'); + return o2.save(); + }) + .then(o => { + assert.equal(o.get('test'), 'changed'); + done(); + }); }); - it('can save a cycle', (done) => { + it('can save a cycle', done => { const a = new TestObject(); const b = new TestObject(); a.set('b', b); - a.save().then(() => { - b.set('a', a); - return b.save(); - }).then(() => { - assert(a.id); - assert(b.id); - assert.equal(a.get('b').id, b.id); - assert.equal(b.get('a').id, a.id); - done(); - }); + a.save() + .then(() => { + b.set('a', a); + return b.save(); + }) + .then(() => { + assert(a.id); + assert(b.id); + assert.equal(a.get('b').id, b.id); + assert.equal(b.get('a').id, a.id); + done(); + }); }); - it('can get objects', (done) => { + it('can get objects', done => { const object = new TestObject({ test: 'test' }); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((o) => { - assert.equal(o.get('test'), 'test'); - assert.equal(o.id, object.id); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('test'), 'test'); + assert.equal(o.id, object.id); + done(); + }); }); - it('can delete an object', (done) => { + it('can delete an object', done => { const object = new TestObject({ test: 'test' }); - object.save().then(() => { - return object.destroy(); - }).then(() => { - return object.fetch(); - }).catch((e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + object + .save() + .then(() => { + return object.destroy(); + }) + .then(() => { + return object.fetch(); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); it('can check if object exists', async () => { @@ -89,39 +101,45 @@ describe('Parse Object', () => { assert.equal(await object.exists(), false); }); - it('can find objects', (done) => { + it('can find objects', done => { const object = new TestObject({ foo: 'bar' }); - object.save().then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('foo', 'bar'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('foo', 'bar'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can establish relational fields', (done) => { + it('can establish relational fields', done => { const item = new Item(); item.set('property', 'x'); const container = new Container(); container.set('item', item); - Parse.Object.saveAll([item, container]).then(() => { - const query = new Parse.Query(Container); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const containerAgain = results[0]; - const itemAgain = containerAgain.get('item'); - return itemAgain.fetch(); - }).then((itemAgain) => { - assert.equal(itemAgain.get('property'), 'x'); - done(); - }); + Parse.Object.saveAll([item, container]) + .then(() => { + const query = new Parse.Query(Container); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const containerAgain = results[0]; + const itemAgain = containerAgain.get('item'); + return itemAgain.fetch(); + }) + .then(itemAgain => { + assert.equal(itemAgain.get('property'), 'x'); + done(); + }); }); - it('adds no fields on save (beyond createdAt and updatedAt)', (done) => { + it('adds no fields on save (beyond createdAt and updatedAt)', done => { const object = new TestObject(); object.save().then(() => { const attributes = object.attributes; @@ -133,88 +151,107 @@ describe('Parse Object', () => { }); }); - it('can perform a recursive save', (done) => { + it('can perform a recursive save', done => { const item = new Item(); item.set('property', 'x'); const container = new Container(); container.set('item', item); - container.save().then(() => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((result) => { - assert(result); - const containerAgain = result; - const itemAgain = containerAgain.get('item'); - return itemAgain.fetch(); - }).then((itemAgain) => { - assert.equal(itemAgain.get('property'), 'x'); - done(); - }); + container + .save() + .then(() => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(result => { + assert(result); + const containerAgain = result; + const itemAgain = containerAgain.get('item'); + return itemAgain.fetch(); + }) + .then(itemAgain => { + assert.equal(itemAgain.get('property'), 'x'); + done(); + }); }); - it('can fetch server data', (done) => { + it('can fetch server data', done => { const item = new Item({ foo: 'bar' }); - item.save().then(() => { - const itemAgain = new Item(); - itemAgain.id = item.id; - return itemAgain.fetch(); - }).then((itemAgain) => { - assert.equal(itemAgain.get('foo'), 'bar'); - return itemAgain.save({ foo: 'baz' }); - }).then(() => { - return item.fetch(); - }).then((itemAgain) => { - assert.equal(item.get('foo'), itemAgain.get('foo')); - done(); - }).catch(done.fail); + item + .save() + .then(() => { + const itemAgain = new Item(); + itemAgain.id = item.id; + return itemAgain.fetch(); + }) + .then(itemAgain => { + assert.equal(itemAgain.get('foo'), 'bar'); + return itemAgain.save({ foo: 'baz' }); + }) + .then(() => { + return item.fetch(); + }) + .then(itemAgain => { + assert.equal(item.get('foo'), itemAgain.get('foo')); + done(); + }) + .catch(done.fail); }); - it('does not remove old fields on fetch', (done) => { + it('does not remove old fields on fetch', done => { const object = new Parse.Object('SimpleObject'); object.set('foo', 'bar'); object.set('test', 'foo'); let object1 = null; let object2 = null; - object.save().then(() => { - const query = new Parse.Query('SimpleObject'); - return query.get(object.id); - }).then((o) => { - object1 = o; - const query = new Parse.Query('SimpleObject'); - return query.get(object.id); - }).then((o) => { - object2 = o; - assert.equal(object1.get('test'), 'foo'); - assert.equal(object2.get('test'), 'foo'); - object2.unset('test'); - return object2.save(); - }).then((o) => { - object2 = o; - return object1.fetch(); - }).then((o) => { - object1 = o; - assert.equal(object2.get('test'), undefined); - assert.equal(object2.get('foo'), 'bar'); - assert.equal(object1.get('test'), undefined); - assert.equal(object1.get('foo'), 'bar'); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query('SimpleObject'); + return query.get(object.id); + }) + .then(o => { + object1 = o; + const query = new Parse.Query('SimpleObject'); + return query.get(object.id); + }) + .then(o => { + object2 = o; + assert.equal(object1.get('test'), 'foo'); + assert.equal(object2.get('test'), 'foo'); + object2.unset('test'); + return object2.save(); + }) + .then(o => { + object2 = o; + return object1.fetch(); + }) + .then(o => { + object1 = o; + assert.equal(object2.get('test'), undefined); + assert.equal(object2.get('foo'), 'bar'); + assert.equal(object1.get('test'), undefined); + assert.equal(object1.get('foo'), 'bar'); + done(); + }); }); - it('does not change createdAt', (done) => { + it('does not change createdAt', done => { const object = new TestObject({ foo: 'bar' }); - object.save().then(() => { - const objectAgain = new TestObject(); - objectAgain.id = object.id; - return objectAgain.fetch(); - }).then((o) => { - assert.equal(o.createdAt.getTime(), object.createdAt.getTime()); - done(); - }); + object + .save() + .then(() => { + const objectAgain = new TestObject(); + objectAgain.id = object.id; + return objectAgain.fetch(); + }) + .then(o => { + assert.equal(o.createdAt.getTime(), object.createdAt.getTime()); + done(); + }); }); - it('exposes createdAt and updatedAt as top level properties', (done) => { + it('exposes createdAt and updatedAt as top level properties', done => { const object = new TestObject({ foo: 'bar' }); object.save().then(() => { assert(object.updatedAt); @@ -223,7 +260,7 @@ describe('Parse Object', () => { }); }); - it('produces a reasonable createdAt time', (done) => { + it('produces a reasonable createdAt time', done => { const start = new Date(); const object = new TestObject({ foo: 'bar' }); object.save().then(() => { @@ -261,11 +298,20 @@ describe('Parse Object', () => { assert.equal(obj.get('objectField').number, 5); assert.equal(obj.get('objectField').letter, 'a'); await obj.save(); - assert.deepStrictEqual(obj.attributes.objectField, { number: 5, letter: 'a' }); + assert.deepStrictEqual(obj.attributes.objectField, { + number: 5, + letter: 'a', + }); obj.increment('objectField.number', 15); - assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' }); - assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' }); + assert.deepStrictEqual(obj.attributes.objectField, { + number: 20, + letter: 'a', + }); + assert.deepStrictEqual(obj.attributes.objectField, { + number: 20, + letter: 'a', + }); assert.equal(obj.get('objectField').number, 20); assert.equal(obj.get('objectField').letter, 'a'); @@ -273,13 +319,19 @@ describe('Parse Object', () => { assert.equal(obj.get('objectField').number, 20); assert.equal(obj.get('objectField').letter, 'a'); - assert.deepStrictEqual(obj.attributes.objectField, { number: 20, letter: 'a' }); + assert.deepStrictEqual(obj.attributes.objectField, { + number: 20, + letter: 'a', + }); const query = new Parse.Query('TestIncrementObject'); const result = await query.get(obj.id); assert.equal(result.get('objectField').number, 20); assert.equal(result.get('objectField').letter, 'a'); - assert.deepStrictEqual(result.attributes.objectField, { number: 20, letter: 'a' }); + assert.deepStrictEqual(result.attributes.objectField, { + number: 20, + letter: 'a', + }); }); it('can increment non existing field', async () => { @@ -323,11 +375,14 @@ describe('Parse Object', () => { await obj.save(); obj.increment('hello.dot', 15); - try { + try { await obj.save(); assert.equal(false, true); - } catch(error) { - assert.equal(error.message, 'schema mismatch for TestObject.hello; expected String but got Object'); + } catch (error) { + assert.equal( + error.message, + 'schema mismatch for TestObject.hello; expected String but got Object' + ); } }); @@ -389,7 +444,7 @@ describe('Parse Object', () => { objectField: { number: 5, string: 'hello', - } + }, }); await obj.save(); @@ -411,7 +466,7 @@ describe('Parse Object', () => { bar: 5, }, string: 'hello', - } + }, }); await obj.save(); @@ -440,7 +495,7 @@ describe('Parse Object', () => { assert.equal(result.get('objectField').unknown, undefined); }); - it('can set keys to null', (done) => { + it('can set keys to null', done => { const obj = new TestObject(); obj.set('foo', null); obj.save().then(() => { @@ -449,7 +504,7 @@ describe('Parse Object', () => { }); }); - it('can set boolean fields', (done) => { + it('can set boolean fields', done => { const obj = new TestObject(); obj.set('yes', true); obj.set('no', false); @@ -460,7 +515,7 @@ describe('Parse Object', () => { }); }); - it('cannot set an invalid date', (done) => { + it('cannot set an invalid date', done => { const obj = new TestObject(); obj.set('when', new Date(Date.parse(null))); obj.save().catch(() => { @@ -468,17 +523,17 @@ describe('Parse Object', () => { }); }); - it('cannot create invalid class names', (done) => { + it('cannot create invalid class names', done => { const item = new Parse.Object('Foo^Bar'); item.save().catch(() => { done(); }); }); - it('cannot create invalid key names', (done) => { + it('cannot create invalid key names', done => { const item = new Parse.Object('Item'); assert(!item.set({ 'foo^bar': 'baz' })); - item.save({ 'foo^bar': 'baz' }).catch((e) => { + item.save({ 'foo^bar': 'baz' }).catch(e => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); @@ -486,35 +541,41 @@ describe('Parse Object', () => { it('cannot use invalid key names in multiple sets', () => { const item = new Parse.Object('Item'); - assert(!item.set({ - 'foobar': 'baz', - 'foo^bar': 'baz' - })); + assert( + !item.set({ + foobar: 'baz', + 'foo^bar': 'baz', + }) + ); assert(!item.get('foobar')); }); - it('can unset fields', (done) => { + it('can unset fields', done => { const simple = new Parse.Object('SimpleObject'); - simple.save({ foo: 'bar' }).then(() => { - simple.unset('foo'); - assert(!simple.has('foo')); - assert(simple.dirty('foo')); - assert(simple.dirty()); - return simple.save(); - }).then(() => { - assert(!simple.has('foo')); - assert(!simple.dirty('foo')); - assert(!simple.dirty()); - - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert(!s.has('foo')); - done(); - }); + simple + .save({ foo: 'bar' }) + .then(() => { + simple.unset('foo'); + assert(!simple.has('foo')); + assert(simple.dirty('foo')); + assert(simple.dirty()); + return simple.save(); + }) + .then(() => { + assert(!simple.has('foo')); + assert(!simple.dirty('foo')); + assert(!simple.dirty()); + + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert(!s.has('foo')); + done(); + }); }); - it('can delete fields before the first save', (done) => { + it('can delete fields before the first save', done => { const simple = new Parse.Object('SimpleObject'); simple.set('foo', 'bar'); simple.unset('foo'); @@ -522,92 +583,111 @@ describe('Parse Object', () => { assert(!simple.has('foo')); assert(simple.dirty('foo')); assert(simple.dirty()); - simple.save().then(() => { - assert(!simple.has('foo')); - assert(!simple.dirty('foo')); - assert(!simple.dirty()); - - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert(!s.has('foo')); - done(); - }); + simple + .save() + .then(() => { + assert(!simple.has('foo')); + assert(!simple.dirty('foo')); + assert(!simple.dirty()); + + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert(!s.has('foo')); + done(); + }); }); - it('can delete pointers', (done) => { + it('can delete pointers', done => { const simple = new Parse.Object('SimpleObject'); const child = new Parse.Object('Child'); - simple.save({ child: child }).then(() => { - simple.unset('child'); - assert(!simple.has('child')); - assert(simple.dirty('child')); - assert(simple.dirty()); - return simple.save(); - }).then(() => { - assert(!simple.has('child')); - assert(!simple.dirty('child')); - assert(!simple.dirty()); - - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert(!s.has('foo')); - done(); - }); + simple + .save({ child: child }) + .then(() => { + simple.unset('child'); + assert(!simple.has('child')); + assert(simple.dirty('child')); + assert(simple.dirty()); + return simple.save(); + }) + .then(() => { + assert(!simple.has('child')); + assert(!simple.dirty('child')); + assert(!simple.dirty()); + + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert(!s.has('foo')); + done(); + }); }); - it('clears deleted keys', (done) => { + it('clears deleted keys', done => { const simple = new Parse.Object('SimpleObject'); simple.set('foo', 'bar'); simple.unset('foo'); - simple.save().then(() => { - simple.set('foo', 'baz'); - return simple.save(); - }).then(() => { - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert.equal(s.get('foo'), 'baz'); - done(); - }); + simple + .save() + .then(() => { + simple.set('foo', 'baz'); + return simple.save(); + }) + .then(() => { + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert.equal(s.get('foo'), 'baz'); + done(); + }); }); - it('can set keys after deleting them', (done) => { + it('can set keys after deleting them', done => { const simple = new Parse.Object('SimpleObject'); - simple.set('foo', 'bar') - simple.save().then(() => { - simple.unset('foo'); - simple.set('foo', 'baz'); - return simple.save(); - }).then(() => { - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert.equal(s.get('foo'), 'baz'); - done(); - }); + simple.set('foo', 'bar'); + simple + .save() + .then(() => { + simple.unset('foo'); + simple.set('foo', 'baz'); + return simple.save(); + }) + .then(() => { + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert.equal(s.get('foo'), 'baz'); + done(); + }); }); - it('can increment fields', (done) => { + it('can increment fields', done => { const simple = new Parse.Object('SimpleObject'); - simple.save({ count: 5 }).then(() => { - simple.increment('count'); - assert.equal(simple.get('count'), 6); - assert(simple.dirty('count')); - assert(simple.dirty()); - return simple.save(); - }).then(() => { - assert.equal(simple.get('count'), 6); - assert(!simple.dirty('count')); - assert(!simple.dirty()); - - const query = new Parse.Query('SimpleObject'); - return query.get(simple.id); - }).then((s) => { - assert.equal(s.get('count'), 6); - done(); - }); + simple + .save({ count: 5 }) + .then(() => { + simple.increment('count'); + assert.equal(simple.get('count'), 6); + assert(simple.dirty('count')); + assert(simple.dirty()); + return simple.save(); + }) + .then(() => { + assert.equal(simple.get('count'), 6); + assert(!simple.dirty('count')); + assert(!simple.dirty()); + + const query = new Parse.Query('SimpleObject'); + return query.get(simple.id); + }) + .then(s => { + assert.equal(s.get('count'), 6); + done(); + }); }); it('can set the object id', () => { @@ -618,7 +698,7 @@ describe('Parse Object', () => { assert.equal(object.id, 'bar'); }); - it('can mark dirty attributes', (done) => { + it('can mark dirty attributes', done => { const object = new TestObject(); object.set('cat', 'goog'); object.set('dog', 'bad'); @@ -637,7 +717,7 @@ describe('Parse Object', () => { }); }); - it('can collect dirty keys', (done) => { + it('can collect dirty keys', done => { const object = new TestObject(); object.set('dog', 'good'); object.set('cat', 'bad'); @@ -647,303 +727,354 @@ describe('Parse Object', () => { assert(dirtyKeys.indexOf('dog') > -1); assert(dirtyKeys.indexOf('cat') > -1); - object.save().then(() => { - assert(!object.dirty()); - dirtyKeys = object.dirtyKeys(); - assert.equal(dirtyKeys.length, 0); - assert(dirtyKeys.indexOf('dog') < 0); - assert(dirtyKeys.indexOf('cat') < 0); - - object.unset('cat'); - assert(object.dirty()); - dirtyKeys = object.dirtyKeys(); - assert.equal(dirtyKeys.length, 1); - assert(dirtyKeys.indexOf('dog') < 0); - assert(dirtyKeys.indexOf('cat') > -1); - - return object.save(); - }).then(() => { - assert(!object.dirty()); - assert.equal(object.get('dog'), 'good'); - assert.equal(object.get('cat'), undefined); - dirtyKeys = object.dirtyKeys(); - assert.equal(dirtyKeys.length, 0); - assert(dirtyKeys.indexOf('dog') < 0); - assert(dirtyKeys.indexOf('cat') < 0); - done(); - }); + object + .save() + .then(() => { + assert(!object.dirty()); + dirtyKeys = object.dirtyKeys(); + assert.equal(dirtyKeys.length, 0); + assert(dirtyKeys.indexOf('dog') < 0); + assert(dirtyKeys.indexOf('cat') < 0); + + object.unset('cat'); + assert(object.dirty()); + dirtyKeys = object.dirtyKeys(); + assert.equal(dirtyKeys.length, 1); + assert(dirtyKeys.indexOf('dog') < 0); + assert(dirtyKeys.indexOf('cat') > -1); + + return object.save(); + }) + .then(() => { + assert(!object.dirty()); + assert.equal(object.get('dog'), 'good'); + assert.equal(object.get('cat'), undefined); + dirtyKeys = object.dirtyKeys(); + assert.equal(dirtyKeys.length, 0); + assert(dirtyKeys.indexOf('dog') < 0); + assert(dirtyKeys.indexOf('cat') < 0); + done(); + }); }); - it('can set ops directly', (done) => { + it('can set ops directly', done => { const object = new Parse.Object('TestObject'); object.set({ cat: 'good', dog: 'bad' }); - object.save().then(() => { - assert.equal(object.get('cat'), 'good'); - - object.set({ x: { __op: 'Increment', amount: 5 }}); - assert.equal(object.get('x'), 5); - assert(object.dirty()); - assert(object.dirty('x')); - assert(!object.dirty('cat')); - assert(object.op('x') instanceof Parse.Op.Increment); - assert.equal(object.op('x')._amount, 5); - - object.set({ x: { __op: 'Increment', amount: 2 }}); - assert.equal(object.get('x'), 7); - assert(object.op('x') instanceof Parse.Op.Increment); - assert.equal(object.op('x')._amount, 7); - - object.set({ cat: { __op: 'Delete' }}); - assert(!object.has('cat')); - assert(object.op('cat') instanceof Parse.Op.Unset); - - const Related = Parse.Object.extend('RelatedObject'); - const relatedObjects = []; - for (let i = 0; i < 5; i++) { - relatedObjects.push(new Related({ i: i })); - } - return Parse.Object.saveAll(relatedObjects).then(() => { - object.set({ - relation: { - __op: 'Batch', - ops: [{ - __op: 'AddRelation', - objects: [relatedObjects[0], relatedObjects[1]] - }, { - __op: 'AddRelation', - objects: [relatedObjects[2], relatedObjects[3]] - }] - } - }); - let relation = object.op('relation'); - assert(relation instanceof Parse.Op.Relation); - assert.equal(relation.relationsToAdd.length, 4); - - object.set({ - relation: { - __op: 'RemoveRelation', - objects: [relatedObjects[1], relatedObjects[4]] - } - }); - - relation = object.op('relation'); - assert(relation instanceof Parse.Op.Relation); - assert.equal(relation.relationsToAdd.length, 3); - assert.equal(relation.relationsToRemove.length, 2); - - }).then(done).catch(done.fail); - }).catch(done.fail); - }); - - it('can repeatedly unset old attributes', (done) => { + object + .save() + .then(() => { + assert.equal(object.get('cat'), 'good'); + + object.set({ x: { __op: 'Increment', amount: 5 } }); + assert.equal(object.get('x'), 5); + assert(object.dirty()); + assert(object.dirty('x')); + assert(!object.dirty('cat')); + assert(object.op('x') instanceof Parse.Op.Increment); + assert.equal(object.op('x')._amount, 5); + + object.set({ x: { __op: 'Increment', amount: 2 } }); + assert.equal(object.get('x'), 7); + assert(object.op('x') instanceof Parse.Op.Increment); + assert.equal(object.op('x')._amount, 7); + + object.set({ cat: { __op: 'Delete' } }); + assert(!object.has('cat')); + assert(object.op('cat') instanceof Parse.Op.Unset); + + const Related = Parse.Object.extend('RelatedObject'); + const relatedObjects = []; + for (let i = 0; i < 5; i++) { + relatedObjects.push(new Related({ i: i })); + } + return Parse.Object.saveAll(relatedObjects) + .then(() => { + object.set({ + relation: { + __op: 'Batch', + ops: [ + { + __op: 'AddRelation', + objects: [relatedObjects[0], relatedObjects[1]], + }, + { + __op: 'AddRelation', + objects: [relatedObjects[2], relatedObjects[3]], + }, + ], + }, + }); + let relation = object.op('relation'); + assert(relation instanceof Parse.Op.Relation); + assert.equal(relation.relationsToAdd.length, 4); + + object.set({ + relation: { + __op: 'RemoveRelation', + objects: [relatedObjects[1], relatedObjects[4]], + }, + }); + + relation = object.op('relation'); + assert(relation instanceof Parse.Op.Relation); + assert.equal(relation.relationsToAdd.length, 3); + assert.equal(relation.relationsToRemove.length, 2); + }) + .then(done) + .catch(done.fail); + }) + .catch(done.fail); + }); + + it('can repeatedly unset old attributes', done => { const obj = new TestObject(); obj.set('x', 3); - obj.save().then(() => { - obj.unset('x'); - obj.unset('x'); - return obj.save(); - }).then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + obj.unset('x'); + obj.unset('x'); + return obj.save(); + }) + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can repeatedly unset new attributes', (done) => { + it('can repeatedly unset new attributes', done => { const obj = new TestObject(); obj.set('x', 5); obj.unset('x'); obj.unset('x'); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can repeatedly unset an unknown attributes', (done) => { + it('can repeatedly unset an unknown attributes', done => { const obj = new TestObject(); obj.unset('x'); obj.unset('x'); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can unset then clear old attributes', (done) => { + it('can unset then clear old attributes', done => { const obj = new TestObject(); obj.set('x', 3); - obj.save().then(() => { - obj.unset('x'); - obj.clear(); - return obj.save(); - }).then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + obj.unset('x'); + obj.clear(); + return obj.save(); + }) + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can unset then clear new attributes', (done) => { + it('can unset then clear new attributes', done => { const obj = new TestObject(); obj.set('x', 5); obj.unset('x'); obj.clear(); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can unset then clear unknown attributes', (done) => { + it('can unset then clear unknown attributes', done => { const obj = new TestObject(); obj.unset('x'); obj.clear(); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then unset old attributes', (done) => { + it('can clear then unset old attributes', done => { const obj = new TestObject(); obj.set('x', 3); - obj.save().then(() => { - obj.clear(); - obj.unset('x'); - return obj.save(); - }).then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + obj.clear(); + obj.unset('x'); + return obj.save(); + }) + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then unset new attributes', (done) => { + it('can clear then unset new attributes', done => { const obj = new TestObject(); obj.set('x', 5); obj.clear(); obj.unset('x'); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then unset unknown attributes', (done) => { + it('can clear then unset unknown attributes', done => { const obj = new TestObject(); obj.clear(); obj.unset('x'); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then clear old attributes', (done) => { + it('can clear then clear old attributes', done => { const obj = new TestObject(); obj.set('x', 3); - obj.save().then(() => { - obj.clear(); - obj.clear(); - return obj.save(); - }).then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + obj.clear(); + obj.clear(); + return obj.save(); + }) + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then clear new attributes', (done) => { + it('can clear then clear new attributes', done => { const obj = new TestObject(); obj.set('x', 5); obj.clear(); obj.clear(); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can clear then clear unknown attributes', (done) => { + it('can clear then clear unknown attributes', done => { const obj = new TestObject(); obj.clear(); obj.clear(); - obj.save().then(() => { - assert.equal(obj.has('x'), false); - assert.equal(obj.get('x'), undefined); - const query = new Parse.Query(TestObject); - return query.get(obj.id); - }).then((o) => { - assert.equal(o.has('x'), false); - assert.equal(o.get('x'), undefined); - done(); - }); + obj + .save() + .then(() => { + assert.equal(obj.has('x'), false); + assert.equal(obj.get('x'), undefined); + const query = new Parse.Query(TestObject); + return query.get(obj.id); + }) + .then(o => { + assert.equal(o.has('x'), false); + assert.equal(o.get('x'), undefined); + done(); + }); }); - it('can save children in an array', (done) => { + it('can save children in an array', done => { const Parent = Parse.Object.extend('Parent'); const Child = Parse.Object.extend('Child'); @@ -957,20 +1088,23 @@ describe('Parse Object', () => { child2.set('house', 'lannister'); parent.set('children', [child1, child2]); - parent.save().then(() => { - const query = new Parse.Query(Child); - query.equalTo('house', 'lannister'); - query.ascending('name'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'cersei'); - assert.equal(results[1].get('name'), 'jaime'); - done(); - }); + parent + .save() + .then(() => { + const query = new Parse.Query(Child); + query.equalTo('house', 'lannister'); + query.ascending('name'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].get('name'), 'cersei'); + assert.equal(results[1].get('name'), 'jaime'); + done(); + }); }); - it('can skip cascade saving as per request', async(done) => { + it('can skip cascade saving as per request', async done => { const Parent = Parse.Object.extend('Parent'); const Child = Parse.Object.extend('Child'); @@ -1008,7 +1142,7 @@ describe('Parse Object', () => { done(); }); - it('can do two saves at the same time', (done) => { + it('can do two saves at the same time', done => { const object = new TestObject(); let firstSave = true; @@ -1020,82 +1154,96 @@ describe('Parse Object', () => { const query = new Parse.Query('TestObject'); query.equalTo('test', 'doublesave'); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); assert.equal(results[0].get('cat'), 'meow'); assert.equal(results[0].get('dog'), 'bark'); done(); }); - } + }; object.save({ cat: 'meow', test: 'doublesave' }).then(success); object.save({ dog: 'bark', test: 'doublesave' }).then(success); }); - it('can achieve a save after failure', (done) => { + it('can achieve a save after failure', done => { const object = new TestObject(); let other; object.set('number', 1); - object.save().then(() => { - other = new TestObject(); - other.set('number', 'two'); - return other.save(); - }).catch((e) => { - assert.equal(e.code, Parse.Error.INCORRECT_TYPE); - other.set('number', 2); - return other.save(); - }).then(() => { - done(); - }); + object + .save() + .then(() => { + other = new TestObject(); + other.set('number', 'two'); + return other.save(); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.INCORRECT_TYPE); + other.set('number', 2); + return other.save(); + }) + .then(() => { + done(); + }); }); - it('is not dirty after save', (done) => { + it('is not dirty after save', done => { const object = new TestObject(); - object.save().then(() => { - object.set({ content: 'x' }); - assert(object.dirty('content')); - return object.fetch(); - }).then(() => { - assert(!object.dirty('content')); - done(); - }); + object + .save() + .then(() => { + object.set({ content: 'x' }); + assert(object.dirty('content')); + return object.fetch(); + }) + .then(() => { + assert(!object.dirty('content')); + done(); + }); }); - it('can add objects to an array', (done) => { + it('can add objects to an array', done => { const child = new Parse.Object('Person'); const parent = new Parse.Object('Person'); - child.save().then(() => { - parent.add('children', child); - return parent.save(); - }).then(() => { - const query = new Parse.Query('Person'); - return query.get(parent.id); - }).then((p) => { - assert.equal(p.get('children')[0].id, child.id); - done(); - }); + child + .save() + .then(() => { + parent.add('children', child); + return parent.save(); + }) + .then(() => { + const query = new Parse.Query('Person'); + return query.get(parent.id); + }) + .then(p => { + assert.equal(p.get('children')[0].id, child.id); + done(); + }); }); - it('can add objects to an array in batch mode', (done) => { + it('can add objects to an array in batch mode', done => { const child1 = new Parse.Object('Person'); const child2 = new Parse.Object('Person'); const parent = new Parse.Object('Person'); - Promise.all([child1.save(), child2.save()]).then((children) => { - parent.addAll('children', children); - return parent.save(); - }).then(() => { - const query = new Parse.Query('Person'); - return query.get(parent.id); - }).then((p) => { - assert.equal(p.get('children')[0].id, child1.id); - assert.equal(p.get('children')[1].id, child2.id); - done(); - }); + Promise.all([child1.save(), child2.save()]) + .then(children => { + parent.addAll('children', children); + return parent.save(); + }) + .then(() => { + const query = new Parse.Query('Person'); + return query.get(parent.id); + }) + .then(p => { + assert.equal(p.get('children')[0].id, child1.id); + assert.equal(p.get('children')[1].id, child2.id); + done(); + }); }); - it('can convert saved objects to json', (done) => { + it('can convert saved objects to json', done => { const object = new TestObject(); object.save({ foo: 'bar' }).then(() => { const json = object.toJSON(); @@ -1117,227 +1265,257 @@ describe('Parse Object', () => { assert(!json.updatedAt); }); - it('can remove objects from array fields', (done) => { + it('can remove objects from array fields', done => { const object = new TestObject(); let container; - object.save().then(() => { - container = new TestObject(); - container.add('array', object); - assert.equal(container.get('array').length, 1); - return container.save(); - }).then(() => { - const o = new TestObject(); - o.id = object.id; - container.remove('array', o); - assert.equal(container.get('array').length, 0); - done(); - }); + object + .save() + .then(() => { + container = new TestObject(); + container.add('array', object); + assert.equal(container.get('array').length, 1); + return container.save(); + }) + .then(() => { + const o = new TestObject(); + o.id = object.id; + container.remove('array', o); + assert.equal(container.get('array').length, 0); + done(); + }); }); - it('can remove objects from array fields in batch mode', (done) => { + it('can remove objects from array fields in batch mode', done => { const obj1 = new TestObject(); const obj2 = new TestObject(); - Promise.all([obj1.save(), obj2.save()]).then((objects) => { - const container = new TestObject(); - container.addAll('array', objects); - assert.equal(container.get('array').length, 2); - return container.save(); - }).then((container) => { - const o1 = new TestObject(); - o1.id = obj1.id; - const o2 = new TestObject(); - o2.id = obj2.id; - const o3 = new TestObject(); - o3.id = 'there_is_no_such_object' - - container.removeAll('array', [o1, o2, o3]); - assert.equal(container.get('array').length, 0); - done(); - }); + Promise.all([obj1.save(), obj2.save()]) + .then(objects => { + const container = new TestObject(); + container.addAll('array', objects); + assert.equal(container.get('array').length, 2); + return container.save(); + }) + .then(container => { + const o1 = new TestObject(); + o1.id = obj1.id; + const o2 = new TestObject(); + o2.id = obj2.id; + const o3 = new TestObject(); + o3.id = 'there_is_no_such_object'; + + container.removeAll('array', [o1, o2, o3]); + assert.equal(container.get('array').length, 0); + done(); + }); }); - it('can perform async methods', (done) => { + it('can perform async methods', done => { const object = new TestObject(); object.set('time', 'adventure'); - object.save().then(() => { - assert(object.id); - const again = new TestObject(); - again.id = object.id; - return again.fetch(); - }).then((again) => { - assert.equal(again.get('time'), 'adventure'); - return again.destroy(); - }).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('objectId', object.id); - return query.find(); - }).then((results) => { - assert.equal(results.length, 0); - done(); - }); + object + .save() + .then(() => { + assert(object.id); + const again = new TestObject(); + again.id = object.id; + return again.fetch(); + }) + .then(again => { + assert.equal(again.get('time'), 'adventure'); + return again.destroy(); + }) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('objectId', object.id); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 0); + done(); + }); }); - it('fails validation with a promise', (done) => { + it('fails validation with a promise', done => { const PickyEater = Parse.Object.extend('PickyEater', { - validate: function(attrs) { + validate: function (attrs) { if (attrs.meal === 'tomatoes') { return 'Ew. Gross.'; } return Parse.Object.prototype.validate.apply(this, arguments); - } + }, }); const bryan = new PickyEater(); - bryan.save({ meal: 'burrito' }).then(() => { - return bryan.save({ meal: 'tomatoes' }); - }).catch((e) => { - assert.equal(e, 'Ew. Gross.'); - done(); - }); + bryan + .save({ meal: 'burrito' }) + .then(() => { + return bryan.save({ meal: 'tomatoes' }); + }) + .catch(e => { + assert.equal(e, 'Ew. Gross.'); + done(); + }); }); - it('works with bytes type', (done) => { + it('works with bytes type', done => { const object = new TestObject(); object.set('bytes', { __type: 'Bytes', base64: 'ZnJveW8=' }); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id) - }).then((o) => { - assert.equal(o.get('bytes').__type, 'Bytes'); - assert.equal(o.get('bytes').base64, 'ZnJveW8='); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(o => { + assert.equal(o.get('bytes').__type, 'Bytes'); + assert.equal(o.get('bytes').base64, 'ZnJveW8='); + done(); + }); }); - it('can destroyAll with no objects', (done) => { + it('can destroyAll with no objects', done => { Parse.Object.destroyAll([]).then(() => { done(); }); }); - it('can destroyAll unsaved objects', (done) => { + it('can destroyAll unsaved objects', done => { const objects = [new TestObject(), new TestObject()]; Parse.Object.destroyAll(objects).then(() => { done(); }); }); - it('can destroyAll a single object', (done) => { + it('can destroyAll a single object', done => { const o = new TestObject(); - o.save().then(() => { - return Parse.Object.destroyAll([o]); - }).then(() => { - const query = new Parse.Query(TestObject); - return query.get(o.id); - }).catch((e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + o.save() + .then(() => { + return Parse.Object.destroyAll([o]); + }) + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(o.id); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); - it('can destroyAll two batches', (done) => { + it('can destroyAll two batches', done => { const objects = []; for (let i = 0; i < 21; i++) { objects[i] = new TestObject(); } - Parse.Object.saveAll(objects).then(() => { - return Parse.Object.destroyAll(objects); - }).then(() => { - const query = new Parse.Query(TestObject); - query.containedIn('objectId', [objects[0].id, objects[20].id]); - return query.find(); - }).then((results) => { - assert.equal(results.length, 0); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + return Parse.Object.destroyAll(objects); + }) + .then(() => { + const query = new Parse.Query(TestObject); + query.containedIn('objectId', [objects[0].id, objects[20].id]); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 0); + done(); + }); }); - it('can destroyAll an object that does not exist', (done) => { + it('can destroyAll an object that does not exist', done => { const o = new TestObject(); o.id = 'fakeobject'; - Parse.Object.destroyAll([o]).catch((e) => { + Parse.Object.destroyAll([o]).catch(e => { assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); assert.equal(e.errors.length, 1); done(); }); }); - it('can destroyAll two batches when the first object does not exist', (done) => { + it('can destroyAll two batches when the first object does not exist', done => { const objects = []; for (let i = 0; i < 21; i++) { objects[i] = new TestObject(); } - Parse.Object.saveAll(objects).then(() => { - objects[0].id = 'fakeobject'; - return Parse.Object.destroyAll(objects); - }).catch((e) => { - assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); - assert.equal(e.errors.length, 1); - assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[0].object, objects[0]); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + objects[0].id = 'fakeobject'; + return Parse.Object.destroyAll(objects); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); + assert.equal(e.errors.length, 1); + assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[0].object, objects[0]); + done(); + }); }); - it('can destroyAll two batches when a middle object does not exist', (done) => { + it('can destroyAll two batches when a middle object does not exist', done => { const objects = []; for (let i = 0; i < 21; i++) { objects[i] = new TestObject(); } - Parse.Object.saveAll(objects).then(() => { - objects[19].id = 'fakeobject'; - return Parse.Object.destroyAll(objects); - }).catch((e) => { - assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); - assert.equal(e.errors.length, 1); - assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[0].object, objects[19]); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + objects[19].id = 'fakeobject'; + return Parse.Object.destroyAll(objects); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); + assert.equal(e.errors.length, 1); + assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[0].object, objects[19]); + done(); + }); }); - it('can destroyAll two batches when the last object does not exist', (done) => { + it('can destroyAll two batches when the last object does not exist', done => { const objects = []; for (let i = 0; i < 21; i++) { objects[i] = new TestObject(); } - Parse.Object.saveAll(objects).then(() => { - objects[20].id = 'fakeobject'; - return Parse.Object.destroyAll(objects); - }).catch((e) => { - assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); - assert.equal(e.errors.length, 1); - assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[0].object, objects[20]); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + objects[20].id = 'fakeobject'; + return Parse.Object.destroyAll(objects); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); + assert.equal(e.errors.length, 1); + assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[0].object, objects[20]); + done(); + }); }); - it('can destroyAll two batches with multiple missing objects', (done) => { + it('can destroyAll two batches with multiple missing objects', done => { const objects = []; for (let i = 0; i < 21; i++) { objects[i] = new TestObject(); } - Parse.Object.saveAll(objects).then(() => { - objects[0].id = 'fakeobject'; - objects[19].id = 'fakeobject'; - objects[20].id = 'fakeobject'; - return Parse.Object.destroyAll(objects); - }).catch((e) => { - assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); - assert.equal(e.errors.length, 3); - assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[1].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[2].code, Parse.Error.OBJECT_NOT_FOUND); - assert.equal(e.errors[0].object, objects[0]); - assert.equal(e.errors[1].object, objects[19]); - assert.equal(e.errors[2].object, objects[20]); - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + objects[0].id = 'fakeobject'; + objects[19].id = 'fakeobject'; + objects[20].id = 'fakeobject'; + return Parse.Object.destroyAll(objects); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.AGGREGATE_ERROR); + assert.equal(e.errors.length, 3); + assert.equal(e.errors[0].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[1].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[2].code, Parse.Error.OBJECT_NOT_FOUND); + assert.equal(e.errors[0].object, objects[0]); + assert.equal(e.errors[1].object, objects[19]); + assert.equal(e.errors[2].object, objects[20]); + done(); + }); }); - it('can fetchAll', (done) => { + it('can fetchAll', done => { const numItems = 11; const container = new Container(); const items = []; @@ -1346,82 +1524,96 @@ describe('Parse Object', () => { item.set('x', i); items.push(item); } - Parse.Object.saveAll(items).then(() => { - container.set('items', items); - return container.save(); - }).then(() => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((containerAgain) => { - const itemsAgain = containerAgain.get('items'); - assert.equal(itemsAgain.length, numItems); - itemsAgain.forEach((item, i) => { - const newValue = i * 2; - item.set('x', newValue); - }); - return Parse.Object.saveAll(itemsAgain); - }).then(() => { - return Parse.Object.fetchAll(items); - }).then((itemsAgain) => { - assert.equal(itemsAgain.length, numItems); - itemsAgain.forEach((item, i) => { - assert.equal(item.get('x'), i * 2); + Parse.Object.saveAll(items) + .then(() => { + container.set('items', items); + return container.save(); + }) + .then(() => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(containerAgain => { + const itemsAgain = containerAgain.get('items'); + assert.equal(itemsAgain.length, numItems); + itemsAgain.forEach((item, i) => { + const newValue = i * 2; + item.set('x', newValue); + }); + return Parse.Object.saveAll(itemsAgain); + }) + .then(() => { + return Parse.Object.fetchAll(items); + }) + .then(itemsAgain => { + assert.equal(itemsAgain.length, numItems); + itemsAgain.forEach((item, i) => { + assert.equal(item.get('x'), i * 2); + }); + done(); }); - done(); - }); }); - it('can fetchAll with no objects', (done) => { + it('can fetchAll with no objects', done => { Parse.Object.fetchAll([]).then(() => { done(); }); }); - it('updates dates on fetchAll', (done) => { + it('updates dates on fetchAll', done => { let updated; const object = new TestObject(); object.set('x', 7); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((result) => { - updated = result; - updated.set('x', 11); - return updated.save(); - }).then(() => { - return Parse.Object.fetchAll([object]); - }).then(() => { - assert.equal(object.createdAt.getTime(), updated.createdAt.getTime()); - assert.equal(object.updatedAt.getTime(), updated.updatedAt.getTime()); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(result => { + updated = result; + updated.set('x', 11); + return updated.save(); + }) + .then(() => { + return Parse.Object.fetchAll([object]); + }) + .then(() => { + assert.equal(object.createdAt.getTime(), updated.createdAt.getTime()); + assert.equal(object.updatedAt.getTime(), updated.updatedAt.getTime()); + done(); + }); }); it('fails fetchAll on multiple classes', () => { const container = new Container(); container.set('item', new Item()); container.set('subcontainer', new Container()); - return container.save().then(() => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((containerAgain) => { - const subContainerAgain = containerAgain.get('subcontainer'); - const itemAgain = containerAgain.get('item'); - const multiClassArray = [subContainerAgain, itemAgain]; - return Parse.Object.fetchAll(multiClassArray); - }).catch((e) => { - assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); - }); + return container + .save() + .then(() => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(containerAgain => { + const subContainerAgain = containerAgain.get('subcontainer'); + const itemAgain = containerAgain.get('item'); + const multiClassArray = [subContainerAgain, itemAgain]; + return Parse.Object.fetchAll(multiClassArray); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); + }); }); it('fails fetchAll on unsaved object', () => { const unsavedObjectArray = [new TestObject()]; - return Parse.Object.fetchAll(unsavedObjectArray).catch((e) => { + return Parse.Object.fetchAll(unsavedObjectArray).catch(e => { assert.equal(e.code, Parse.Error.MISSING_OBJECT_ID); }); }); - it('fails fetchAll on deleted object', (done) => { + it('fails fetchAll on deleted object', done => { const numItems = 11; const items = []; for (let i = 0; i < numItems; i++) { @@ -1429,55 +1621,73 @@ describe('Parse Object', () => { item.set('x', i); items.push(item); } - Parse.Object.saveAll(items).then(() => { - const query = new Parse.Query(Item); - return query.get(items[0].id); - }).then((objectToDelete) => { - return objectToDelete.destroy(); - }).then((deletedObject) => { - const nonExistentObject = new Item({ objectId: deletedObject.id }); - const nonExistentObjectArray = [nonExistentObject, items[1]]; - return Parse.Object.fetchAll(nonExistentObjectArray); - }).catch((e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + Parse.Object.saveAll(items) + .then(() => { + const query = new Parse.Query(Item); + return query.get(items[0].id); + }) + .then(objectToDelete => { + return objectToDelete.destroy(); + }) + .then(deletedObject => { + const nonExistentObject = new Item({ objectId: deletedObject.id }); + const nonExistentObjectArray = [nonExistentObject, items[1]]; + return Parse.Object.fetchAll(nonExistentObjectArray); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); - it('merges user attributes on fetchAll', (done) => { + it('merges user attributes on fetchAll', done => { Parse.User.enableUnsafeCurrentUser(); let sameUser; let user = new Parse.User(); user.set('username', 'asdf'); user.set('password', 'zxcv'); user.set('foo', 'bar'); - user.signUp().then(() => { - Parse.User.logOut(); - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((userAgain) => { - user = userAgain; - sameUser = new Parse.User(); - sameUser.set('username', 'asdf'); - sameUser.set('password', 'zxcv'); - return sameUser.logIn(); - }).then(() => { - assert(!user.getSessionToken()); - assert(sameUser.getSessionToken()); - sameUser.set('baz', 'qux'); - return sameUser.save(); - }).then(() => { - return Parse.Object.fetchAll([user]); - }).then(() => { - assert.equal(user.createdAt.getTime(), sameUser.createdAt.getTime()); - assert.equal(user.updatedAt.getTime(), sameUser.updatedAt.getTime()); - return Parse.User.logOut().then(() => { done(); }, () => { done(); }); - }).catch(done.fail); + user + .signUp() + .then(() => { + Parse.User.logOut(); + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(userAgain => { + user = userAgain; + sameUser = new Parse.User(); + sameUser.set('username', 'asdf'); + sameUser.set('password', 'zxcv'); + return sameUser.logIn(); + }) + .then(() => { + assert(!user.getSessionToken()); + assert(sameUser.getSessionToken()); + sameUser.set('baz', 'qux'); + return sameUser.save(); + }) + .then(() => { + return Parse.Object.fetchAll([user]); + }) + .then(() => { + assert.equal(user.createdAt.getTime(), sameUser.createdAt.getTime()); + assert.equal(user.updatedAt.getTime(), sameUser.updatedAt.getTime()); + return Parse.User.logOut().then( + () => { + done(); + }, + () => { + done(); + } + ); + }) + .catch(done.fail); }); it('can fetchAllIfNeededWithInclude', async () => { const pointer = new TestObject({ foo: 'bar' }); - const item1 = new Item({ x: 1}); + const item1 = new Item({ x: 1 }); const item2 = new Item({ x: 2, pointer }); const items = [item1, item2]; @@ -1498,7 +1708,10 @@ describe('Parse Object', () => { // Override item1 in database, this shouldn't fetch await item1Again.save(); - const fetchedItems = await Parse.Object.fetchAllIfNeededWithInclude([item1, item2Again], ['pointer']); + const fetchedItems = await Parse.Object.fetchAllIfNeededWithInclude( + [item1, item2Again], + ['pointer'] + ); assert.equal(fetchedItems.length, items.length); assert.equal(fetchedItems[0].get('x'), 1); assert.equal(fetchedItems[1].get('x'), 2); // item2Again should update @@ -1506,7 +1719,7 @@ describe('Parse Object', () => { assert.equal(fetchedItems[1].get('pointer').get('foo'), 'bar'); }); - it('can fetchAllIfNeeded', (done) => { + it('can fetchAllIfNeeded', done => { const numItems = 11; const container = new Container(); const items = []; @@ -1515,38 +1728,43 @@ describe('Parse Object', () => { item.set('x', i); items.push(item); } - Parse.Object.saveAll(items).then(() => { - container.set('items', items); - return container.save(); - }).then(() => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((containerAgain) => { - const itemsAgain = containerAgain.get('items'); - itemsAgain.forEach((item, i) => { - item.set('x', i * 2); - }); - return Parse.Object.saveAll(itemsAgain); - }).then(() => { - return Parse.Object.fetchAllIfNeeded(items); - }).then((fetchedItems) => { - assert.equal(fetchedItems.length, numItems); - fetchedItems.forEach((item, i) => { - assert.equal(item.get('x'), i); + Parse.Object.saveAll(items) + .then(() => { + container.set('items', items); + return container.save(); + }) + .then(() => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(containerAgain => { + const itemsAgain = containerAgain.get('items'); + itemsAgain.forEach((item, i) => { + item.set('x', i * 2); + }); + return Parse.Object.saveAll(itemsAgain); + }) + .then(() => { + return Parse.Object.fetchAllIfNeeded(items); + }) + .then(fetchedItems => { + assert.equal(fetchedItems.length, numItems); + fetchedItems.forEach((item, i) => { + assert.equal(item.get('x'), i); + }); + done(); }); - done(); - }); }); - it('can fetchAllIfNeeded with no objects', (done) => { + it('can fetchAllIfNeeded with no objects', done => { Parse.Object.fetchAllIfNeeded([]).then(() => { done(); }); }); - it('can fetchAllIfNeeded with an unsaved object', (done) => { + it('can fetchAllIfNeeded with an unsaved object', done => { const unsavedObjectArray = [new TestObject()]; - Parse.Object.fetchAllIfNeeded(unsavedObjectArray).catch((e) => { + Parse.Object.fetchAllIfNeeded(unsavedObjectArray).catch(e => { assert.equal(e.code, Parse.Error.MISSING_OBJECT_ID); done(); }); @@ -1556,23 +1774,27 @@ describe('Parse Object', () => { const container = new Container(); container.set('item', new Item()); container.set('subcontainer', new Container()); - return container.save().then(() => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((containerAgain) => { - const subContainerAgain = containerAgain.get('subcontainer'); - const itemAgain = containerAgain.get('item'); - const multiClassArray = [subContainerAgain, itemAgain]; - return Parse.Object.fetchAllIfNeeded(multiClassArray); - }).catch((e) => { - assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); - }); + return container + .save() + .then(() => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(containerAgain => { + const subContainerAgain = containerAgain.get('subcontainer'); + const itemAgain = containerAgain.get('item'); + const multiClassArray = [subContainerAgain, itemAgain]; + return Parse.Object.fetchAllIfNeeded(multiClassArray); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.INVALID_CLASS_NAME); + }); }); - it('can rewrite the User classname', (done) => { + it('can rewrite the User classname', done => { assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), true); const User1 = Parse.Object.extend({ - className: 'User' + className: 'User', }); assert.equal(User1.className, '_User'); @@ -1580,7 +1802,7 @@ describe('Parse Object', () => { Parse.User.allowCustomUserClass(true); assert.equal(Parse.CoreManager.get('PERFORM_USER_REWRITE'), false); const User2 = Parse.Object.extend({ - className: 'User' + className: 'User', }); assert.equal(User2.className, 'User'); @@ -1590,35 +1812,41 @@ describe('Parse Object', () => { const user = new User2(); user.set('name', 'Me'); - user.save({ height: 181 }).then(() => { - assert.equal(user.get('name'), 'Me'); - assert.equal(user.get('height'), 181); + user + .save({ height: 181 }) + .then(() => { + assert.equal(user.get('name'), 'Me'); + assert.equal(user.get('height'), 181); + + const query = new Parse.Query(User2); + return query.get(user.id); + }) + .then(() => { + assert.equal(user.className, 'User'); + assert.equal(user.get('name'), 'Me'); + assert.equal(user.get('height'), 181); - const query = new Parse.Query(User2); - return query.get(user.id); - }).then(() => { - assert.equal(user.className, 'User'); - assert.equal(user.get('name'), 'Me'); - assert.equal(user.get('height'), 181); - - done(); - }); + done(); + }); }); - it('can create objects without data', (done) => { + it('can create objects without data', done => { const t1 = new TestObject({ test: 'test' }); - t1.save().then(() => { - const t2 = TestObject.createWithoutData(t1.id); - return t2.fetch(); - }).then((t2) => { - assert.equal(t2.get('test'), 'test'); - const t3 = TestObject.createWithoutData(t2.id); - t3.set('test', 'not test'); - return t3.fetch(); - }).then((t3) => { - assert.equal(t3.get('test'), 'test'); - done(); - }); + t1.save() + .then(() => { + const t2 = TestObject.createWithoutData(t1.id); + return t2.fetch(); + }) + .then(t2 => { + assert.equal(t2.get('test'), 'test'); + const t3 = TestObject.createWithoutData(t2.id); + t3.set('test', 'not test'); + return t3.fetch(); + }) + .then(t3 => { + assert.equal(t3.get('test'), 'test'); + done(); + }); }); it('can fetchWithInclude', async () => { @@ -1639,7 +1867,7 @@ describe('Parse Object', () => { assert.equal(fetchedObj2.get('child').get('field'), 'isChild'); const obj3 = TestObject.createWithoutData(parent.id); - const fetchedObj3 = await obj3.fetchWithInclude([ ['child'] ]); + const fetchedObj3 = await obj3.fetchWithInclude([['child']]); assert.equal(obj3.get('child').get('field'), 'isChild'); assert.equal(fetchedObj3.get('child').get('field'), 'isChild'); }); @@ -1662,7 +1890,7 @@ describe('Parse Object', () => { assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj3 = TestObject.createWithoutData(parent.id); - await obj3.fetchWithInclude([ ['child.grandchild'] ]); + await obj3.fetchWithInclude([['child.grandchild']]); assert.equal(obj3.get('child').get('grandchild').get('field'), 'isGrandchild'); }); @@ -1682,7 +1910,7 @@ describe('Parse Object', () => { assert.equal(obj2.get('child').get('field'), 'isChild'); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [ ['child'] ]); + await Parse.Object.fetchAllWithInclude([obj3], [['child']]); assert.equal(obj3.get('child').get('field'), 'isChild'); }); @@ -1704,13 +1932,13 @@ describe('Parse Object', () => { assert.equal(obj2.get('child').get('grandchild').get('field'), 'isGrandchild'); const obj3 = TestObject.createWithoutData(parent.id); - await Parse.Object.fetchAllWithInclude([obj3], [ ['child.grandchild'] ]); + await Parse.Object.fetchAllWithInclude([obj3], [['child.grandchild']]); assert.equal(obj3.get('child').get('grandchild').get('field'), 'isGrandchild'); }); - it('fires errors when readonly attributes are changed', (done) => { + it('fires errors when readonly attributes are changed', done => { const LimitedObject = Parse.Object.extend('LimitedObject'); - LimitedObject.readOnlyAttributes = function() { + LimitedObject.readOnlyAttributes = function () { return ['immutable']; }; @@ -1722,9 +1950,9 @@ describe('Parse Object', () => { } }); - it('fires errors when readonly attributes are unset', (done) => { + it('fires errors when readonly attributes are unset', done => { const LimitedObject = Parse.Object.extend('LimitedObject'); - LimitedObject.readOnlyAttributes = function() { + LimitedObject.readOnlyAttributes = function () { return ['immutable']; }; @@ -1736,7 +1964,7 @@ describe('Parse Object', () => { } }); - it('can clone with relation', async (done) => { + it('can clone with relation', async done => { const testObject = new TestObject(); const o = new TestObject(); await o.save(); @@ -1746,10 +1974,7 @@ describe('Parse Object', () => { await o.save(); const o2 = o.clone(); - assert.equal( - o.relation('aRelation').targetClassName, - o2.relation('aRelation').targetClassName - ); + assert.equal(o.relation('aRelation').targetClassName, o2.relation('aRelation').targetClassName); let relations = await o.relation('aRelation').query().find(); assert.equal(relations.length, 1); diff --git a/integration/test/ParsePolygonTest.js b/integration/test/ParsePolygonTest.js index 38b4de4e9..6c95c34b1 100644 --- a/integration/test/ParsePolygonTest.js +++ b/integration/test/ParsePolygonTest.js @@ -11,62 +11,87 @@ describe('Polygon', () => { Parse.Storage._clear(); }); - beforeEach((done) => { + beforeEach(done => { clear().then(() => { done(); }); }); - it('can save polygon with points', (done) => { - const openPoints = [[0,0], [0,1], [1,1], [1,0]]; - const closedPoints = [[0,0], [0,1], [1,1], [1,0], [0,0]]; + it('can save polygon with points', done => { + const openPoints = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const closedPoints = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const polygon = new Parse.Polygon(openPoints); const obj = new TestObject({ polygon }); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('polygon', polygon); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); - const closedPolygon = new Parse.Polygon(closedPoints); - const query = new Parse.Query(TestObject); - query.equalTo('polygon', closedPolygon); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); - done(); - }, done.fail); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('polygon', polygon); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); + const closedPolygon = new Parse.Polygon(closedPoints); + const query = new Parse.Query(TestObject); + query.equalTo('polygon', closedPolygon); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); + done(); + }, done.fail); }); - it('can save polygon with GeoPoints', (done) => { + it('can save polygon with GeoPoints', done => { const p1 = new Parse.GeoPoint(0, 0); const p2 = new Parse.GeoPoint(0, 1); const p3 = new Parse.GeoPoint(1, 1); const p4 = new Parse.GeoPoint(1, 0); const p5 = new Parse.GeoPoint(0, 0); - const closedPoints = [[0,0], [0,1], [1,1], [1,0], [0,0]]; + const closedPoints = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const polygon = new Parse.Polygon([p1, p2, p3, p4, p5]); const obj = new TestObject({ polygon }); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('polygon', polygon); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); - const closedPolygon = new Parse.Polygon(closedPoints); - const query = new Parse.Query(TestObject); - query.equalTo('polygon', closedPolygon); - return query.find(); - }).then((results) => { - assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); - done(); - }, done.fail); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('polygon', polygon); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); + const closedPolygon = new Parse.Polygon(closedPoints); + const query = new Parse.Query(TestObject); + query.equalTo('polygon', closedPolygon); + return query.find(); + }) + .then(results => { + assert.deepEqual(results[0].get('polygon').coordinates, closedPoints); + done(); + }, done.fail); }); - it('fail save with 3 point minumum', (done) => { + it('fail save with 3 point minumum', done => { try { new Parse.Polygon([[0, 0]]); } catch (e) { @@ -74,7 +99,7 @@ describe('Polygon', () => { } }); - it('fail save with non array', (done) => { + it('fail save with non array', done => { try { new Parse.Polygon(123); } catch (e) { @@ -82,7 +107,7 @@ describe('Polygon', () => { } }); - it('fail save with invalid array', (done) => { + it('fail save with invalid array', done => { try { new Parse.Polygon([['str1'], ['str2'], ['str3']]); } catch (e) { @@ -90,8 +115,13 @@ describe('Polygon', () => { } }); - it('containsPoint', (done) => { - const points = [[0,0], [0,1], [1,1], [1,0]]; + it('containsPoint', done => { + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; const inside = new Parse.GeoPoint(0.5, 0.5); const outside = new Parse.GeoPoint(10, 10); const polygon = new Parse.Polygon(points); @@ -101,9 +131,19 @@ describe('Polygon', () => { done(); }); - it('equality', (done) => { - const points = [[0,0], [0,1], [1,1], [1,0]]; - const diff = [[0,0], [0,2], [2,2], [2,0]]; + it('equality', done => { + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const diff = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; const polygonA = new Parse.Polygon(points); const polygonB = new Parse.Polygon(points); @@ -119,10 +159,26 @@ describe('Polygon', () => { done(); }); - it('supports polygonContains', (done) => { - const p1 = [[0,0], [0,1], [1,1], [1,0]]; - const p2 = [[0,0], [0,2], [2,2], [2,0]]; - const p3 = [[10,10], [10,15], [15,15], [15,10], [10,10]]; + it('supports polygonContains', done => { + const p1 = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const p2 = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; + const p3 = [ + [10, 10], + [10, 15], + [15, 15], + [15, 10], + [10, 10], + ]; const polygon1 = new Parse.Polygon(p1); const polygon2 = new Parse.Polygon(p2); @@ -132,29 +188,40 @@ describe('Polygon', () => { const obj2 = new TestObject({ polygon: polygon2 }); const obj3 = new TestObject({ polygon: polygon3 }); - Parse.Object.saveAll([obj1, obj2, obj3]).then(() => { - const point = new Parse.GeoPoint(0.5, 0.5); - const query = new Parse.Query(TestObject); - query.polygonContains('polygon', point); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - done(); - }, done.fail); + Parse.Object.saveAll([obj1, obj2, obj3]) + .then(() => { + const point = new Parse.GeoPoint(0.5, 0.5); + const query = new Parse.Query(TestObject); + query.polygonContains('polygon', point); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + done(); + }, done.fail); }); - it('polygonContains invalid input', (done) => { - const points = [[0,0], [0,1], [1,1], [1,0]]; + it('polygonContains invalid input', done => { + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; const polygon = new Parse.Polygon(points); const obj = new TestObject({ polygon }); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.polygonContains('polygon', 1234); - return query.find(); - }).then(() => { - fail(); - }).catch(() => { - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.polygonContains('polygon', 1234); + return query.find(); + }) + .then(() => { + fail(); + }) + .catch(() => { + done(); + }); }); }); diff --git a/integration/test/ParseQueryAggregateTest.js b/integration/test/ParseQueryAggregateTest.js index cdff28378..8d763944e 100644 --- a/integration/test/ParseQueryAggregateTest.js +++ b/integration/test/ParseQueryAggregateTest.js @@ -7,45 +7,52 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Parse Aggregate Query', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - clear().then(() => { - const obj1 = new TestObject({score: 10, name: 'foo'}); - const obj2 = new TestObject({score: 10, name: 'foo'}); - const obj3 = new TestObject({score: 10, name: 'bar'}); - const obj4 = new TestObject({score: 20, name: 'dpl'}); - return Parse.Object.saveAll([obj1, obj2, obj3, obj4]); - }).then(() => { - return Parse.User.logOut(); - }) - .then(() => { done() }, () => { done() }); + clear() + .then(() => { + const obj1 = new TestObject({ score: 10, name: 'foo' }); + const obj2 = new TestObject({ score: 10, name: 'foo' }); + const obj3 = new TestObject({ score: 10, name: 'bar' }); + const obj4 = new TestObject({ score: 20, name: 'dpl' }); + return Parse.Object.saveAll([obj1, obj2, obj3, obj4]); + }) + .then(() => { + return Parse.User.logOut(); + }) + .then( + () => { + done(); + }, + () => { + done(); + } + ); }); - it('aggregate pipeline object query', (done) => { + it('aggregate pipeline object query', done => { const pipeline = { group: { objectId: '$name' }, }; const query = new Parse.Query(TestObject); - query.aggregate(pipeline).then((results) => { + query.aggregate(pipeline).then(results => { assert.equal(results.length, 3); done(); }); }); - it('aggregate pipeline array query', (done) => { - const pipeline = [ - { group: { objectId: '$name' } } - ]; + it('aggregate pipeline array query', done => { + const pipeline = [{ group: { objectId: '$name' } }]; const query = new Parse.Query(TestObject); - query.aggregate(pipeline).then((results) => { + query.aggregate(pipeline).then(results => { assert.equal(results.length, 3); done(); }); }); - it('aggregate pipeline invalid query', (done) => { + it('aggregate pipeline invalid query', done => { const pipeline = 1234; const query = new Parse.Query(TestObject); try { @@ -64,29 +71,35 @@ describe('Parse Aggregate Query', () => { const obj2 = new TestObject({ pointer: pointer2, name: 'Hello' }); const obj3 = new TestObject({ pointer: pointer3, name: 'World' }); - const pipeline = [{ - match: { name: 'Hello' }, - }, { - // Transform className$objectId to objectId and store in new field tempPointer - project: { - tempPointer: { $substr: ['$_p_pointer', 11, -1] }, // Remove TestObject$ + const pipeline = [ + { + match: { name: 'Hello' }, }, - }, { - // Left Join, replace objectId stored in tempPointer with an actual object - lookup: { - from: 'TestObject', - localField: 'tempPointer', - foreignField: '_id', - as: 'tempPointer', + { + // Transform className$objectId to objectId and store in new field tempPointer + project: { + tempPointer: { $substr: ['$_p_pointer', 11, -1] }, // Remove TestObject$ + }, }, - }, { - // lookup returns an array, Deconstructs an array field to objects - unwind: { - path: '$tempPointer', + { + // Left Join, replace objectId stored in tempPointer with an actual object + lookup: { + from: 'TestObject', + localField: 'tempPointer', + foreignField: '_id', + as: 'tempPointer', + }, }, - }, { - match: { 'tempPointer.value': 2 }, - }]; + { + // lookup returns an array, Deconstructs an array field to objects + unwind: { + path: '$tempPointer', + }, + }, + { + match: { 'tempPointer.value': 2 }, + }, + ]; await Parse.Object.saveAll([pointer1, pointer2, pointer3, obj1, obj2, obj3]); const query = new Parse.Query(TestObject); @@ -100,15 +113,11 @@ describe('Parse Aggregate Query', () => { const pipeline = { group: { objectId: '$name' }, }; - let results = await new Parse.Query(TestObject) - .equalTo('name', 'foo') - .aggregate(pipeline); + let results = await new Parse.Query(TestObject).equalTo('name', 'foo').aggregate(pipeline); expect(results.length).toBe(1); - results = await new Parse.Query(TestObject) - .equalTo('score', 20) - .aggregate(pipeline); + results = await new Parse.Query(TestObject).equalTo('score', 20).aggregate(pipeline); expect(results.length).toBe(1); @@ -117,7 +126,7 @@ describe('Parse Aggregate Query', () => { it('distinct query', () => { const query = new Parse.Query(TestObject); - return query.distinct('score').then((results) => { + return query.distinct('score').then(results => { assert.equal(results.length, 2); // Order the results in case const orderedResults = results.sort((a, b) => a - b); @@ -126,10 +135,10 @@ describe('Parse Aggregate Query', () => { }); }); - it('distinct equalTo query', (done) => { + it('distinct equalTo query', done => { const query = new Parse.Query(TestObject); - query.equalTo('name', 'foo') - query.distinct('score').then((results) => { + query.equalTo('name', 'foo'); + query.distinct('score').then(results => { assert.equal(results.length, 1); assert.equal(results[0], 10); done(); diff --git a/integration/test/ParseQueryTest.js b/integration/test/ParseQueryTest.js index 846801455..e71f41ddb 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -7,49 +7,65 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Parse Query', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); - clear().then(() => { - const numbers = []; - for (let i = 0; i < 10; i++) { - numbers[i] = new Parse.Object({ className: 'BoxedNumber', number: i }); - } - return Parse.Object.saveAll(numbers); - }).then(() => { - return Parse.User.logOut(); - }) - .then(() => { done() }, () => { done() }); + clear() + .then(() => { + const numbers = []; + for (let i = 0; i < 10; i++) { + numbers[i] = new Parse.Object({ + className: 'BoxedNumber', + number: i, + }); + } + return Parse.Object.saveAll(numbers); + }) + .then(() => { + return Parse.User.logOut(); + }) + .then( + () => { + done(); + }, + () => { + done(); + } + ); }); - - it('can do basic queries', (done) => { + it('can do basic queries', done => { const baz = new TestObject({ foo: 'baz' }); const qux = new TestObject({ foo: 'qux' }); - Parse.Object.saveAll([baz, qux]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('foo', 'baz'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('foo'), 'baz'); - done(); - }); + Parse.Object.saveAll([baz, qux]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('foo', 'baz'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('foo'), 'baz'); + done(); + }); }); - it('can do a query with a limit', (done) => { + it('can do a query with a limit', done => { const baz = new TestObject({ foo: 'baz' }); const qux = new TestObject({ foo: 'qux' }); - Parse.Object.saveAll([baz, qux]).then(() => { - const query = new Parse.Query(TestObject); - query.limit(1); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); - done(); - }).catch(done.fail); + Parse.Object.saveAll([baz, qux]) + .then(() => { + const query = new Parse.Query(TestObject); + query.limit(1); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(['baz', 'qux'].includes(results[0].get('foo')), true); + done(); + }) + .catch(done.fail); }); it('can do query with count', async () => { @@ -61,13 +77,13 @@ describe('Parse Query', () => { const query = new Parse.Query(TestObject); query.withCount(true); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count === 'number'); assert.equal(results.length, 4); assert.equal(count, 4); for (let i = 0; i < 4; i++) { - assert.equal(results[i].className,'TestObject'); + assert.equal(results[i].className, 'TestObject'); } }); @@ -84,14 +100,14 @@ describe('Parse Query', () => { assert.equal(results.length, 4); for (let i = 0; i < 4; i++) { - assert.equal(results[i].className,'TestObject'); + assert.equal(results[i].className, 'TestObject'); } }); it('can do query with count on empty collection', async () => { const query = new Parse.Query(TestObject); query.withCount(true); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count == 'number'); assert.equal(results.length, 0); @@ -101,14 +117,14 @@ describe('Parse Query', () => { it('can do query with count and limit', async () => { const items = []; for (let i = 0; i < 4; i++) { - items.push(new TestObject({ countMe: 2})); + items.push(new TestObject({ countMe: 2 })); } await Parse.Object.saveAll(items); const query = new Parse.Query(TestObject); query.withCount(true); query.limit(2); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count == 'number'); assert.equal(results.length, 2); @@ -118,14 +134,14 @@ describe('Parse Query', () => { it('can do query withCount and skip', async () => { const items = []; for (let i = 0; i < 4; i++) { - items.push(new TestObject({ countMe: 2})); + items.push(new TestObject({ countMe: 2 })); } await Parse.Object.saveAll(items); const query = new Parse.Query(TestObject); query.withCount(true); query.skip(3); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count == 'number'); assert.equal(results.length, 1); @@ -135,13 +151,13 @@ describe('Parse Query', () => { it('can do query when withCount set without arguments', async () => { const items = []; for (let i = 0; i < 4; i++) { - items.push(new TestObject({ countMe: 2})); + items.push(new TestObject({ countMe: 2 })); } await Parse.Object.saveAll(items); const query = new Parse.Query(TestObject); query.withCount(); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count == 'number'); assert.equal(results.length, 4); @@ -151,21 +167,21 @@ describe('Parse Query', () => { it('can do query when withCount undefined', async () => { const items = []; for (let i = 0; i < 4; i++) { - items.push(new TestObject({ countMe: 2})); + items.push(new TestObject({ countMe: 2 })); } await Parse.Object.saveAll(items); const query = new Parse.Query(TestObject); let foo; query.withCount(foo); - const {results,count} = await query.find(); + const { results, count } = await query.find(); assert(typeof count == 'number'); assert.equal(results.length, 4); assert.equal(count, 4); }); - it('can do containedIn queries with arrays', (done) => { + it('can do containedIn queries with arrays', done => { const messageList = []; for (let i = 0; i < 4; i++) { const message = new Parse.Object('Message'); @@ -175,60 +191,69 @@ describe('Parse Query', () => { messageList.push(message); } - Parse.Object.saveAll(messageList).then(() => { - assert.equal(messageList.length, 4); - - const inList = []; - inList.push(messageList[0]); - inList.push(messageList[2]); - - const query = new Parse.Query('Message'); - query.containedIn('prior', inList); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - done(); - }); + Parse.Object.saveAll(messageList) + .then(() => { + assert.equal(messageList.length, 4); + + const inList = []; + inList.push(messageList[0]); + inList.push(messageList[2]); + + const query = new Parse.Query('Message'); + query.containedIn('prior', inList); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + done(); + }); }); - it('can do containsAll queries with numbers', (done) => { + it('can do containsAll queries with numbers', done => { const NumberSet = Parse.Object.extend('NumberSet'); const objectsList = []; - objectsList.push(new NumberSet({ numbers: [1,2,3,4,5] })); - objectsList.push(new NumberSet({ numbers: [1,3,4,5] })); - Parse.Object.saveAll(objectsList).then(() => { - const query = new Parse.Query(NumberSet); - query.containsAll('numbers', [1,2,3]); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + objectsList.push(new NumberSet({ numbers: [1, 2, 3, 4, 5] })); + objectsList.push(new NumberSet({ numbers: [1, 3, 4, 5] })); + Parse.Object.saveAll(objectsList) + .then(() => { + const query = new Parse.Query(NumberSet); + query.containsAll('numbers', [1, 2, 3]); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can do containsAll queries with strings', (done) => { + it('can do containsAll queries with strings', done => { const StringSet = Parse.Object.extend('StringSet'); const objectsList = []; objectsList.push(new StringSet({ strings: ['a', 'b', 'c', 'd', 'e'] })); objectsList.push(new StringSet({ strings: ['a', 'c', 'd'] })); - Parse.Object.saveAll(objectsList).then(() => { - const query = new Parse.Query(StringSet); - query.containsAll('strings', ['a', 'b', 'c']); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + Parse.Object.saveAll(objectsList) + .then(() => { + const query = new Parse.Query(StringSet); + query.containsAll('strings', ['a', 'b', 'c']); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can do containsAll queries with dates', (done) => { + it('can do containsAll queries with dates', done => { const DateSet = Parse.Object.extend('DateSet'); function parseDate(iso) { const regexp = new RegExp( - '^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})' + 'T' + - '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})' + - '(.([0-9]+))?' + 'Z$'); + '^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})' + + 'T' + + '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})' + + '(.([0-9]+))?' + + 'Z$' + ); const match = regexp.exec(iso); if (!match) { return null; @@ -246,64 +271,72 @@ describe('Parse Query', () => { } function makeDates(stringArray) { - return stringArray.map((date) => { + return stringArray.map(date => { return parseDate(date + 'T00:00:00Z'); }); } const objectsList = []; - objectsList.push(new DateSet({ - dates: makeDates(['2013-02-01', '2013-02-02', '2013-02-03']) - })); - objectsList.push(new DateSet({ - dates: makeDates(['2013-02-01', '2013-02-03', '2013-02-04']) - })); - - Parse.Object.saveAll(objectsList).then(() => { - const query = new Parse.Query(DateSet); - query.containsAll('dates', makeDates( - ['2013-02-01', '2013-02-02', '2013-02-03'] - )); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }).catch(e => console.log(e)); - }); - - it('can do containsAll queries with objects', (done) => { + objectsList.push( + new DateSet({ + dates: makeDates(['2013-02-01', '2013-02-02', '2013-02-03']), + }) + ); + objectsList.push( + new DateSet({ + dates: makeDates(['2013-02-01', '2013-02-03', '2013-02-04']), + }) + ); + + Parse.Object.saveAll(objectsList) + .then(() => { + const query = new Parse.Query(DateSet); + query.containsAll('dates', makeDates(['2013-02-01', '2013-02-02', '2013-02-03'])); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }) + .catch(e => console.log(e)); + }); + + it('can do containsAll queries with objects', done => { const MessageSet = Parse.Object.extend('MessageSet'); const messageList = []; for (let i = 0; i < 4; i++) { - messageList.push(new TestObject({i: i})); + messageList.push(new TestObject({ i: i })); } - Parse.Object.saveAll(messageList).then(() => { - assert.equal(messageList.length, 4); - - const messageSetList = []; - messageSetList.push(new MessageSet({messages: messageList})); - - const someList = []; - someList.push(messageList[0]); - someList.push(messageList[1]); - someList.push(messageList[3]); - messageSetList.push(new MessageSet({messages: someList})); - - return Parse.Object.saveAll(messageSetList); - }).then(() => { - const inList = []; - inList.push(messageList[0]); - inList.push(messageList[2]); - - const query = new Parse.Query(MessageSet); - query.containsAll('messages', inList); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + Parse.Object.saveAll(messageList) + .then(() => { + assert.equal(messageList.length, 4); + + const messageSetList = []; + messageSetList.push(new MessageSet({ messages: messageList })); + + const someList = []; + someList.push(messageList[0]); + someList.push(messageList[1]); + someList.push(messageList[3]); + messageSetList.push(new MessageSet({ messages: someList })); + + return Parse.Object.saveAll(messageSetList); + }) + .then(() => { + const inList = []; + inList.push(messageList[0]); + inList.push(messageList[2]); + + const query = new Parse.Query(MessageSet); + query.containsAll('messages', inList); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); it('can do containedBy queries with numbers', async () => { @@ -322,7 +355,7 @@ describe('Parse Query', () => { }); it('can do containedBy queries with pointer', async () => { - const objects = Array.from(Array(10).keys()).map((idx) => { + const objects = Array.from(Array(10).keys()).map(idx => { const obj = new Parse.Object('Object'); obj.set('key', idx); return obj; @@ -353,707 +386,868 @@ describe('Parse Query', () => { assert.equal(results[0].id, parent3.id); }); - it('can do equalTo queries', (done) => { + it('can do equalTo queries', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('number', 3); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); done(); }); }); - it('can do equalTo queries with object', (done) => { + it('can do equalTo queries with object', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo({ number: 3 }); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); done(); }); }); - it('can test equality with undefined', (done) => { + it('can test equality with undefined', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('number', undefined); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('can perform lessThan queries', (done) => { + it('can perform lessThan queries', done => { const query = new Parse.Query('BoxedNumber'); query.lessThan('number', 7); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 7); done(); }); }); - it('can perform lessThanOrEqualTo queries', (done) => { + it('can perform lessThanOrEqualTo queries', done => { const query = new Parse.Query('BoxedNumber'); query.lessThanOrEqualTo('number', 7); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 8); done(); }); }); - it('can perform greaterThan queries', (done) => { + it('can perform greaterThan queries', done => { const query = new Parse.Query('BoxedNumber'); query.greaterThan('number', 7); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 2); done(); }); }); - it('can perform greaterThanOrEqualTo queries', (done) => { + it('can perform greaterThanOrEqualTo queries', done => { const query = new Parse.Query('BoxedNumber'); query.greaterThanOrEqualTo('number', 7); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 3); done(); }); }); - it('can combine lessThanOrEqualTo and greaterThanOrEqualTo queries', (done) => { + it('can combine lessThanOrEqualTo and greaterThanOrEqualTo queries', done => { const query = new Parse.Query('BoxedNumber'); query.lessThanOrEqualTo('number', 7); query.greaterThanOrEqualTo('number', 7); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 1); done(); }); }); - it('can combine lessThan and greaterThan queries', (done) => { + it('can combine lessThan and greaterThan queries', done => { const query = new Parse.Query('BoxedNumber'); query.lessThan('number', 9); query.greaterThan('number', 3); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 5); done(); }); }); - it('can perform notEqualTo queries', (done) => { + it('can perform notEqualTo queries', done => { const query = new Parse.Query('BoxedNumber'); query.notEqualTo('number', 5); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 9); done(); }); }); - it('can perform notEqualTo queries with object', (done) => { + it('can perform notEqualTo queries with object', done => { const query = new Parse.Query('BoxedNumber'); query.notEqualTo({ number: 5 }); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 9); done(); }); }); - it('can perform containedIn queries', (done) => { + it('can perform containedIn queries', done => { const query = new Parse.Query('BoxedNumber'); - query.containedIn('number', [3,5,7,9,11]); - query.find().then((results) => { + query.containedIn('number', [3, 5, 7, 9, 11]); + query.find().then(results => { assert.equal(results.length, 4); done(); }); }); - it('can perform notContainedIn queries', (done) => { + it('can perform notContainedIn queries', done => { const query = new Parse.Query('BoxedNumber'); - query.notContainedIn('number', [3,5,7,9,11]); - query.find().then((results) => { + query.notContainedIn('number', [3, 5, 7, 9, 11]); + query.find().then(results => { assert.equal(results.length, 6); done(); }); }); - it('can test objectId in containedIn queries', (done) => { - new Parse.Query('BoxedNumber').ascending('number').find().then((numbers) => { - const ids = [numbers[2].id, numbers[3].id, 'nonsense']; - const query = new Parse.Query('BoxedNumber'); - query.containedIn('objectId', ids); - query.ascending('number'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].get('number'), 2); - assert.equal(results[1].get('number'), 3); - done(); - }); + it('can test objectId in containedIn queries', done => { + new Parse.Query('BoxedNumber') + .ascending('number') + .find() + .then(numbers => { + const ids = [numbers[2].id, numbers[3].id, 'nonsense']; + const query = new Parse.Query('BoxedNumber'); + query.containedIn('objectId', ids); + query.ascending('number'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].get('number'), 2); + assert.equal(results[1].get('number'), 3); + done(); + }); }); - it('can test objectId in equalTo queries', (done) => { - new Parse.Query('BoxedNumber').ascending('number').find().then((numbers) => { - const id = numbers[5].id; - const query = new Parse.Query('BoxedNumber'); - query.equalTo('objectId', id); - query.ascending('number'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('number'), 5); - done(); - }); + it('can test objectId in equalTo queries', done => { + new Parse.Query('BoxedNumber') + .ascending('number') + .find() + .then(numbers => { + const id = numbers[5].id; + const query = new Parse.Query('BoxedNumber'); + query.equalTo('objectId', id); + query.ascending('number'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('number'), 5); + done(); + }); }); - it('can find no elements', (done) => { + it('can find no elements', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('number', 15); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); done(); }); }); - it('handles when find throws errors', (done) => { + it('handles when find throws errors', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('$foo', 'bar'); - query.find().catch((e) => { + query.find().catch(e => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); }); - it('can get by objectId', (done) => { + it('can get by objectId', done => { const object = new TestObject(); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(object.id); - }).then((result) => { - assert.equal(result.id, object.id); - assert(result.createdAt); - assert(result.updatedAt); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(object.id); + }) + .then(result => { + assert.equal(result.id, object.id); + assert(result.createdAt); + assert(result.updatedAt); + done(); + }); }); - it('handles get with undefined id', (done) => { + it('handles get with undefined id', done => { const object = new TestObject(); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(undefined); - }).catch((e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(undefined); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); - it('handles get with invalid id', (done) => { + it('handles get with invalid id', done => { const object = new TestObject(); - object.save().then(() => { - const query = new Parse.Query(TestObject); - return query.get(undefined); - }).catch((e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(TestObject); + return query.get(undefined); + }) + .catch(e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); - it('can query for the first result', (done) => { + it('can query for the first result', done => { const query = new Parse.Query('BoxedNumber'); query.ascending('number'); - query.first().then((result) => { + query.first().then(result => { assert.equal(result.get('number'), 0); done(); }); }); - it('can query for the first with no results', (done) => { + it('can query for the first with no results', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('number', 20); - query.first().then((result) => { + query.first().then(result => { assert.equal(result, undefined); done(); }); }); - it('can query for the first with two results', (done) => { - Parse.Object.saveAll([new TestObject({x: 44}), new TestObject({x: 44})]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('x', 44); - return query.first() - }).then((result) => { - assert.equal(result.get('x'), 44); - done(); - }); + it('can query for the first with two results', done => { + Parse.Object.saveAll([new TestObject({ x: 44 }), new TestObject({ x: 44 })]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('x', 44); + return query.first(); + }) + .then(result => { + assert.equal(result.get('x'), 44); + done(); + }); }); - it('handles when first throws errors', (done) => { + it('handles when first throws errors', done => { const query = new Parse.Query('BoxedNumber'); query.equalTo('$foo', 'bar'); - query.first().catch((e) => { + query.first().catch(e => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); }); - it('can test object inequality', (done) => { + it('can test object inequality', done => { const item1 = new TestObject(); const item2 = new TestObject(); - const container1 = new Parse.Object({className: 'CoolContainer', item: item1}); - const container2 = new Parse.Object({className: 'CoolContainer', item: item2}); - Parse.Object.saveAll([item1, item2, container1, container2]).then(() => { - const query = new Parse.Query('CoolContainer'); - query.notEqualTo('item', item1); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + const container1 = new Parse.Object({ + className: 'CoolContainer', + item: item1, + }); + const container2 = new Parse.Object({ + className: 'CoolContainer', + item: item2, + }); + Parse.Object.saveAll([item1, item2, container1, container2]) + .then(() => { + const query = new Parse.Query('CoolContainer'); + query.notEqualTo('item', item1); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can skip', (done) => { + it('can skip', done => { Parse.Object.saveAll([ new TestObject({ canSkip: true }), new TestObject({ canSkip: true }), - new TestObject({ canSkip: true }) - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); - query.skip(1); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - const query = new Parse.Query(TestObject); - query.equalTo('canSkip', true); - query.skip(3); - return query.find(); - }).then((results) => { - assert.equal(results.length, 0); - done(); - }); + new TestObject({ canSkip: true }), + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('canSkip', true); + query.skip(1); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + const query = new Parse.Query(TestObject); + query.equalTo('canSkip', true); + query.skip(3); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 0); + done(); + }); }); - it('does not consider skip in count queries', (done) => { + it('does not consider skip in count queries', done => { Parse.Object.saveAll([ new TestObject({ skipCount: true }), new TestObject({ skipCount: true }), - new TestObject({ skipCount: true }) - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); - return query.count(); - }).then((count) => { - assert.equal(count, 3); - const query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); - query.skip(1); - return query.count(); - }).then((count) => { - assert.equal(count, 3); - const query = new Parse.Query(TestObject); - query.equalTo('skipCount', true); - query.skip(2); - return query.count(); - }).then((count) => { - assert.equal(count, 3); - done(); - }); + new TestObject({ skipCount: true }), + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('skipCount', true); + return query.count(); + }) + .then(count => { + assert.equal(count, 3); + const query = new Parse.Query(TestObject); + query.equalTo('skipCount', true); + query.skip(1); + return query.count(); + }) + .then(count => { + assert.equal(count, 3); + const query = new Parse.Query(TestObject); + query.equalTo('skipCount', true); + query.skip(2); + return query.count(); + }) + .then(count => { + assert.equal(count, 3); + done(); + }); }); - it('can perform count queries', (done) => { + it('can perform count queries', done => { const query = new Parse.Query('BoxedNumber'); query.greaterThan('number', 1); - query.count().then((count) => { + query.count().then(count => { assert.equal(count, 8); done(); }); }); - it('can order by ascending numbers', (done) => { + it('can order by ascending numbers', done => { const query = new Parse.Query('BoxedNumber'); query.ascending('number'); - query.find().then((results) => { + query.find().then(results => { assert.equal(results[0].get('number'), 0); assert.equal(results[9].get('number'), 9); done(); }); }); - it('can order by descending numbers', (done) => { + it('can order by descending numbers', done => { const query = new Parse.Query('BoxedNumber'); query.descending('number'); - query.find().then((results) => { + query.find().then(results => { assert.equal(results[0].get('number'), 9); assert.equal(results[9].get('number'), 0); done(); }); }); - it('can order by asecending number then descending string', (done) => { + it('can order by asecending number then descending string', done => { Parse.Object.saveAll([ new TestObject({ doubleOrder: true, number: 3, string: 'a' }), new TestObject({ doubleOrder: true, number: 1, string: 'b' }), new TestObject({ doubleOrder: true, number: 3, string: 'c' }), new TestObject({ doubleOrder: true, number: 2, string: 'd' }), - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('doubleOrder', true); - query.ascending('number').addDescending('string'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 1); - assert.equal(results[0].get('string'), 'b'); - assert.equal(results[1].get('number'), 2); - assert.equal(results[1].get('string'), 'd'); - assert.equal(results[2].get('number'), 3); - assert.equal(results[2].get('string'), 'c'); - assert.equal(results[3].get('number'), 3); - assert.equal(results[3].get('string'), 'a'); - done(); - }); + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('doubleOrder', true); + query.ascending('number').addDescending('string'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 1); + assert.equal(results[0].get('string'), 'b'); + assert.equal(results[1].get('number'), 2); + assert.equal(results[1].get('string'), 'd'); + assert.equal(results[2].get('number'), 3); + assert.equal(results[2].get('string'), 'c'); + assert.equal(results[3].get('number'), 3); + assert.equal(results[3].get('string'), 'a'); + done(); + }); }); - it('can order by descending number then ascending string', (done) => { + it('can order by descending number then ascending string', done => { Parse.Object.saveAll([ new TestObject({ otherDoubleOrder: true, number: 3, string: 'a' }), new TestObject({ otherDoubleOrder: true, number: 1, string: 'b' }), new TestObject({ otherDoubleOrder: true, number: 3, string: 'c' }), new TestObject({ otherDoubleOrder: true, number: 2, string: 'd' }), - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('otherDoubleOrder', true); - query.descending('number').addAscending('string'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 3); - assert.equal(results[0].get('string'), 'a'); - assert.equal(results[1].get('number'), 3); - assert.equal(results[1].get('string'), 'c'); - assert.equal(results[2].get('number'), 2); - assert.equal(results[2].get('string'), 'd'); - assert.equal(results[3].get('number'), 1); - assert.equal(results[3].get('string'), 'b'); - done(); - }); + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('otherDoubleOrder', true); + query.descending('number').addAscending('string'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 3); + assert.equal(results[0].get('string'), 'a'); + assert.equal(results[1].get('number'), 3); + assert.equal(results[1].get('string'), 'c'); + assert.equal(results[2].get('number'), 2); + assert.equal(results[2].get('string'), 'd'); + assert.equal(results[3].get('number'), 1); + assert.equal(results[3].get('string'), 'b'); + done(); + }); }); - it('can order by descending number and string', (done) => { + it('can order by descending number and string', done => { Parse.Object.saveAll([ new TestObject({ doubleDescending: true, number: 3, string: 'a' }), new TestObject({ doubleDescending: true, number: 1, string: 'b' }), new TestObject({ doubleDescending: true, number: 3, string: 'c' }), new TestObject({ doubleDescending: true, number: 2, string: 'd' }), - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number,string'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 3); - assert.equal(results[0].get('string'), 'c'); - assert.equal(results[1].get('number'), 3); - assert.equal(results[1].get('string'), 'a'); - assert.equal(results[2].get('number'), 2); - assert.equal(results[2].get('string'), 'd'); - assert.equal(results[3].get('number'), 1); - assert.equal(results[3].get('string'), 'b'); - - const query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number, string'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 3); - assert.equal(results[0].get('string'), 'c'); - assert.equal(results[1].get('number'), 3); - assert.equal(results[1].get('string'), 'a'); - assert.equal(results[2].get('number'), 2); - assert.equal(results[2].get('string'), 'd'); - assert.equal(results[3].get('number'), 1); - assert.equal(results[3].get('string'), 'b'); - - const query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending(['number', 'string']); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 3); - assert.equal(results[0].get('string'), 'c'); - assert.equal(results[1].get('number'), 3); - assert.equal(results[1].get('string'), 'a'); - assert.equal(results[2].get('number'), 2); - assert.equal(results[2].get('string'), 'd'); - assert.equal(results[3].get('number'), 1); - assert.equal(results[3].get('string'), 'b'); - - const query = new Parse.Query(TestObject); - query.equalTo('doubleDescending', true); - query.descending('number', 'string'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 4); - assert.equal(results[0].get('number'), 3); - assert.equal(results[0].get('string'), 'c'); - assert.equal(results[1].get('number'), 3); - assert.equal(results[1].get('string'), 'a'); - assert.equal(results[2].get('number'), 2); - assert.equal(results[2].get('string'), 'd'); - assert.equal(results[3].get('number'), 1); - assert.equal(results[3].get('string'), 'b'); - - done(); - }); + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('doubleDescending', true); + query.descending('number,string'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 3); + assert.equal(results[0].get('string'), 'c'); + assert.equal(results[1].get('number'), 3); + assert.equal(results[1].get('string'), 'a'); + assert.equal(results[2].get('number'), 2); + assert.equal(results[2].get('string'), 'd'); + assert.equal(results[3].get('number'), 1); + assert.equal(results[3].get('string'), 'b'); + + const query = new Parse.Query(TestObject); + query.equalTo('doubleDescending', true); + query.descending('number, string'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 3); + assert.equal(results[0].get('string'), 'c'); + assert.equal(results[1].get('number'), 3); + assert.equal(results[1].get('string'), 'a'); + assert.equal(results[2].get('number'), 2); + assert.equal(results[2].get('string'), 'd'); + assert.equal(results[3].get('number'), 1); + assert.equal(results[3].get('string'), 'b'); + + const query = new Parse.Query(TestObject); + query.equalTo('doubleDescending', true); + query.descending(['number', 'string']); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 3); + assert.equal(results[0].get('string'), 'c'); + assert.equal(results[1].get('number'), 3); + assert.equal(results[1].get('string'), 'a'); + assert.equal(results[2].get('number'), 2); + assert.equal(results[2].get('string'), 'd'); + assert.equal(results[3].get('number'), 1); + assert.equal(results[3].get('string'), 'b'); + + const query = new Parse.Query(TestObject); + query.equalTo('doubleDescending', true); + query.descending('number', 'string'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 4); + assert.equal(results[0].get('number'), 3); + assert.equal(results[0].get('string'), 'c'); + assert.equal(results[1].get('number'), 3); + assert.equal(results[1].get('string'), 'a'); + assert.equal(results[2].get('number'), 2); + assert.equal(results[2].get('string'), 'd'); + assert.equal(results[3].get('number'), 1); + assert.equal(results[3].get('string'), 'b'); + + done(); + }); }); - it('can not order by password', (done) => { + it('can not order by password', done => { const query = new Parse.Query('BoxedNumber'); query.ascending('_password'); - query.find().catch((e) => { + query.find().catch(e => { assert.equal(e.code, Parse.Error.INVALID_KEY_NAME); done(); }); }); - it('can order by _created_at', (done) => { - new Parse.Object({className: 'TestObject', orderedDate: true}).save().then(() => { - return new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate: true}).save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate', true); - query.ascending('_created_at'); - return query.find() - }).then((results) => { - assert(results[0].createdAt < results[1].createdAt); - assert(results[1].createdAt < results[2].createdAt); - assert(results[2].createdAt < results[3].createdAt); - done(); - }); + it('can order by _created_at', done => { + new Parse.Object({ className: 'TestObject', orderedDate: true }) + .save() + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate: true, + }).save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate', true); + query.ascending('_created_at'); + return query.find(); + }) + .then(results => { + assert(results[0].createdAt < results[1].createdAt); + assert(results[1].createdAt < results[2].createdAt); + assert(results[2].createdAt < results[3].createdAt); + done(); + }); }); - it('can order by createdAt', (done) => { - new Parse.Object({className: 'TestObject', orderedDate2: true}).save().then(() => { - return new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate2: true}).save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate2', true); - query.descending('createdAt'); - return query.find() - }).then((results) => { - assert(results[0].createdAt > results[1].createdAt); - assert(results[1].createdAt > results[2].createdAt); - assert(results[2].createdAt > results[3].createdAt); - done(); - }); + it('can order by createdAt', done => { + new Parse.Object({ className: 'TestObject', orderedDate2: true }) + .save() + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate2: true, + }).save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate2', true); + query.descending('createdAt'); + return query.find(); + }) + .then(results => { + assert(results[0].createdAt > results[1].createdAt); + assert(results[1].createdAt > results[2].createdAt); + assert(results[2].createdAt > results[3].createdAt); + done(); + }); }); - it('can order by _updated_at', (done) => { - new Parse.Object({className: 'TestObject', orderedDate3: true}).save().then(() => { - return new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate3: true}).save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate3', true); - query.ascending('_updated_at'); - return query.find() - }).then((results) => { - assert(results[0].updatedAt < results[1].updatedAt); - assert(results[1].updatedAt < results[2].updatedAt); - assert(results[2].updatedAt < results[3].updatedAt); - done(); - }); + it('can order by _updated_at', done => { + new Parse.Object({ className: 'TestObject', orderedDate3: true }) + .save() + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate3: true, + }).save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate3', true); + query.ascending('_updated_at'); + return query.find(); + }) + .then(results => { + assert(results[0].updatedAt < results[1].updatedAt); + assert(results[1].updatedAt < results[2].updatedAt); + assert(results[2].updatedAt < results[3].updatedAt); + done(); + }); }); - it('can order by updatedAt', (done) => { - new Parse.Object({className: 'TestObject', orderedDate4: true}).save().then(() => { - return new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', orderedDate4: true}).save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - query.equalTo('orderedDate4', true); - query.descending('updatedAt'); - return query.find() - }).then((results) => { - assert(results[0].updatedAt > results[1].updatedAt); - assert(results[1].updatedAt > results[2].updatedAt); - assert(results[2].updatedAt > results[3].updatedAt); - done(); - }); + it('can order by updatedAt', done => { + new Parse.Object({ className: 'TestObject', orderedDate4: true }) + .save() + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + orderedDate4: true, + }).save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.equalTo('orderedDate4', true); + query.descending('updatedAt'); + return query.find(); + }) + .then(results => { + assert(results[0].updatedAt > results[1].updatedAt); + assert(results[1].updatedAt > results[2].updatedAt); + assert(results[2].updatedAt > results[3].updatedAt); + done(); + }); }); - it('can test time equality', (done) => { - new Parse.Object({className: 'TestObject', timed: true, name: 'item1'}).save().then(() => { - return new Parse.Object({className: 'TestObject', timed: true, name: 'item2'}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', timed: true, name: 'item3'}).save(); - }).then(() => { - return new Parse.Object({className: 'TestObject', timed: true, name: 'item4'}).save(); - }).then((last) => { - const query = new Parse.Query('TestObject'); - query.equalTo('timed', true); - query.equalTo('createdAt', last.createdAt); - return query.find() - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'item4'); - done(); - }); + it('can test time equality', done => { + new Parse.Object({ className: 'TestObject', timed: true, name: 'item1' }) + .save() + .then(() => { + return new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item2', + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item3', + }).save(); + }) + .then(() => { + return new Parse.Object({ + className: 'TestObject', + timed: true, + name: 'item4', + }).save(); + }) + .then(last => { + const query = new Parse.Query('TestObject'); + query.equalTo('timed', true); + query.equalTo('createdAt', last.createdAt); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('name'), 'item4'); + done(); + }); }); - it('can test time inequality', (done) => { + it('can test time inequality', done => { const objects = [ - new Parse.Object({className: 'TestObject', timed2: true, name: 'item1'}), - new Parse.Object({className: 'TestObject', timed2: true, name: 'item2'}), - new Parse.Object({className: 'TestObject', timed2: true, name: 'item3'}), - new Parse.Object({className: 'TestObject', timed2: true, name: 'item4'}) + new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item1', + }), + new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item2', + }), + new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item3', + }), + new Parse.Object({ + className: 'TestObject', + timed2: true, + name: 'item4', + }), ]; - objects[0].save().then(() => { - return objects[1].save(); - }).then(() => { - return objects[2].save(); - }).then(() => { - return objects[3].save(); - }).then(() => { - const query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.lessThan('createdAt', objects[2].createdAt); - query.ascending('createdAt'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].id, objects[0].id); - assert.equal(results[1].id, objects[1].id); - - const query = new Parse.Query('TestObject'); - query.equalTo('timed2', true); - query.greaterThan('createdAt', objects[2].createdAt); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].id, objects[3].id); - done(); - }).catch(done.fail); - }); - - it('can test string matching', (done) => { + objects[0] + .save() + .then(() => { + return objects[1].save(); + }) + .then(() => { + return objects[2].save(); + }) + .then(() => { + return objects[3].save(); + }) + .then(() => { + const query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.lessThan('createdAt', objects[2].createdAt); + query.ascending('createdAt'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].id, objects[0].id); + assert.equal(results[1].id, objects[1].id); + + const query = new Parse.Query('TestObject'); + query.equalTo('timed2', true); + query.greaterThan('createdAt', objects[2].createdAt); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].id, objects[3].id); + done(); + }) + .catch(done.fail); + }); + + it('can test string matching', done => { const obj1 = new TestObject(); obj1.set('myString', 'football'); const obj2 = new TestObject(); obj2.set('myString', 'soccer'); - Parse.Object.saveAll([obj1, obj2]).then(() => { - const query = new Parse.Query(TestObject); - query.matches('myString', '^fo*\\wb[^o]l+$'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); - - const query = new Parse.Query(TestObject); - query.matches('myString', /^fo*\wb[^o]l+$/); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'football'); - done(); - }); + Parse.Object.saveAll([obj1, obj2]) + .then(() => { + const query = new Parse.Query(TestObject); + query.matches('myString', '^fo*\\wb[^o]l+$'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('myString'), 'football'); + + const query = new Parse.Query(TestObject); + query.matches('myString', /^fo*\wb[^o]l+$/); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('myString'), 'football'); + done(); + }); }); - it('can test case insensitive regex', (done) => { + it('can test case insensitive regex', done => { const obj = new TestObject(); obj.set('myString', 'hockey'); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.matches('myString', 'Hockey', 'i'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('myString'), 'hockey'); - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.matches('myString', 'Hockey', 'i'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('myString'), 'hockey'); + done(); + }); }); - it('fails for invalid regex options', (done) => { + it('fails for invalid regex options', done => { const query = new Parse.Query(TestObject); query.matches('myString', 'football', 'some invalid thing'); - query.find().catch((e) => { + query.find().catch(e => { assert.equal(e.code, Parse.Error.INVALID_QUERY); done(); }); }); - it('can use a regex with all modifiers', (done) => { + it('can use a regex with all modifiers', done => { const obj = new TestObject(); obj.set('website', 'PArSe\nCom'); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.matches( - 'website', - 'parse # First fragment. We\'ll write this in one case but match ' + - 'insensitively\n.com # Second fragment. This can be separated by any ' + - 'character, including newline\n', - 'mixs' - ); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.matches( + 'website', + "parse # First fragment. We'll write this in one case but match " + + 'insensitively\n.com # Second fragment. This can be separated by any ' + + 'character, including newline\n', + 'mixs' + ); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can include regexp modifiers in the constructor', (done) => { + it('can include regexp modifiers in the constructor', done => { const obj = new TestObject(); obj.set('website', '\n\nbuffer\n\nparse.COM'); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.matches('website', /parse\.com/mi); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.matches('website', /parse\.com/im); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); - it('can test contains', (done) => { - const someAscii = "\\E' !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU" + - "VWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'"; + it('can test contains', done => { + const someAscii = + "\\E' !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTU" + + "VWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'"; Parse.Object.saveAll([ - new TestObject({contains: true, myString: 'zax' + someAscii + 'qub'}), - new TestObject({contains: true, myString: 'start' + someAscii}), - new TestObject({contains: true, myString: someAscii + 'end'}), - new TestObject({contains: true, myString: someAscii}) - ]).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - const query = new Parse.Query(TestObject); - query.equalTo('contains', true); - query.startsWith('myString', someAscii); - return query.find(); - }).then((results) => { - assert.equal(results.length, 2); - done(); - }); + new TestObject({ contains: true, myString: 'zax' + someAscii + 'qub' }), + new TestObject({ contains: true, myString: 'start' + someAscii }), + new TestObject({ contains: true, myString: someAscii + 'end' }), + new TestObject({ contains: true, myString: someAscii }), + ]) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + const query = new Parse.Query(TestObject); + query.equalTo('contains', true); + query.startsWith('myString', someAscii); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 2); + done(); + }); }); - it('can test if a key exists', (done) => { + it('can test if a key exists', done => { const objects = []; for (let i = 0; i < 10; i++) { const item = new TestObject(); @@ -1064,20 +1258,23 @@ describe('Parse Query', () => { } objects.push(item); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - query.exists('y'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 5); - for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); - } - done(); - }).catch(e => console.log(e)); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + query.exists('y'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 5); + for (let i = 0; i < results.length; i++) { + assert(results[i].has('y')); + } + done(); + }) + .catch(e => console.log(e)); }); - it('can test if a key does not exist', (done) => { + it('can test if a key does not exist', done => { const objects = []; for (let i = 0; i < 10; i++) { const item = new TestObject({ dne: true }); @@ -1088,24 +1285,28 @@ describe('Parse Query', () => { } objects.push(item); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('dne', true); - query.doesNotExist('y'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 5); - for (let i = 0; i < results.length; i++) { - assert(results[i].has('z')); - } - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('dne', true); + query.doesNotExist('y'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 5); + for (let i = 0; i < results.length; i++) { + assert(results[i].has('z')); + } + done(); + }); }); - it('can test if a relation exists', (done) => { + it('can test if a relation exists', done => { const objects = []; for (let i = 0; i < 10; i++) { - const container = new Parse.Object('Container', { relation_exists: true }); + const container = new Parse.Object('Container', { + relation_exists: true, + }); if (i % 2) { container.set('y', i); } else { @@ -1116,21 +1317,23 @@ describe('Parse Query', () => { } objects.push(container); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query('Container'); - query.equalTo('relation_exists', true); - query.exists('x'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 5); - for (let i = 0; i < results.length; i++) { - assert(results[i].has('x')); - } - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query('Container'); + query.equalTo('relation_exists', true); + query.exists('x'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 5); + for (let i = 0; i < results.length; i++) { + assert(results[i].has('x')); + } + done(); + }); }); - it('can test if a relation does not exist', (done) => { + it('can test if a relation does not exist', done => { const objects = []; for (let i = 0; i < 10; i++) { const container = new Parse.Object('Container', { relation_dne: true }); @@ -1144,57 +1347,64 @@ describe('Parse Query', () => { } objects.push(container); } - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query('Container'); - query.equalTo('relation_dne', true); - query.doesNotExist('x'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 5); - for (let i = 0; i < results.length; i++) { - assert(results[i].has('y')); - } - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query('Container'); + query.equalTo('relation_dne', true); + query.doesNotExist('x'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 5); + for (let i = 0; i < results.length; i++) { + assert(results[i].has('y')); + } + done(); + }); }); - it('does not include by default', (done) => { + it('does not include by default', done => { const child = new TestObject(); const parent = new Parse.Object('Container'); child.set('foo', 'bar'); parent.set('child', child); - Parse.Object.saveAll([child, parent]).then(() => { - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const parentAgain = results[0]; - assert(parentAgain.get('child')); - assert(parentAgain.get('child').id); - assert(!parentAgain.get('child').get('foo')); - done(); - }).catch(e => console.log(e)); - }); - - it('can include nested objects', (done) => { + Parse.Object.saveAll([child, parent]) + .then(() => { + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const parentAgain = results[0]; + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert(!parentAgain.get('child').get('foo')); + done(); + }) + .catch(e => console.log(e)); + }); + + it('can include nested objects', done => { const child = new TestObject(); const parent = new Parse.Object('Container'); child.set('foo', 'bar'); parent.set('child', child); - Parse.Object.saveAll([child, parent]).then(() => { - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include('child'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const parentAgain = results[0]; - assert(parentAgain.get('child')); - assert(parentAgain.get('child').id); - assert.equal(parentAgain.get('child').get('foo'), 'bar'); - done(); - }); + Parse.Object.saveAll([child, parent]) + .then(() => { + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include('child'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const parentAgain = results[0]; + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert.equal(parentAgain.get('child').get('foo'), 'bar'); + done(); + }); }); it('can includeAll nested objects', async () => { @@ -1234,7 +1444,7 @@ describe('Parse Query', () => { query.equalTo('objectId', parent.id); query.includeAll(); - await query.each((obj) => { + await query.each(obj => { assert.equal(obj.get('child1').get('foo'), 'bar'); assert.equal(obj.get('child2').get('foo'), 'baz'); assert.equal(obj.get('child3').get('foo'), 'bin'); @@ -1253,27 +1463,29 @@ describe('Parse Query', () => { assert.equal(result.length, 101); }); - it('can include nested objects via array', (done) => { + it('can include nested objects via array', done => { const child = new TestObject(); const parent = new Parse.Object('Container'); child.set('foo', 'bar'); parent.set('child', child); - Parse.Object.saveAll([child, parent]).then(() => { - const query = new Parse.Query('Container'); - query.equalTo('objectId', parent.id); - query.include(['child']); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const parentAgain = results[0]; - assert(parentAgain.get('child')); - assert(parentAgain.get('child').id); - assert.equal(parentAgain.get('child').get('foo'), 'bar'); - done(); - }); + Parse.Object.saveAll([child, parent]) + .then(() => { + const query = new Parse.Query('Container'); + query.equalTo('objectId', parent.id); + query.include(['child']); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const parentAgain = results[0]; + assert(parentAgain.get('child')); + assert(parentAgain.get('child').id); + assert.equal(parentAgain.get('child').get('foo'), 'bar'); + done(); + }); }); - it('can do a nested include', (done) => { + it('can do a nested include', done => { const Child = Parse.Object.extend('Child'); const Parent = Parse.Object.extend('Parent'); const Grandparent = Parse.Object.extend('Grandparent'); @@ -1286,7 +1498,7 @@ describe('Parse Query', () => { parent: new Parent({ y: i, child: new Child({ - x: i + x: i, }), }), }); @@ -1294,43 +1506,47 @@ describe('Parse Query', () => { objects.push(grandparent); } - Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query('Grandparent'); - q.equalTo('nested', true); - q.include('parent.child'); - return q.find(); - }).then((results) => { - assert.equal(results.length, 5); - results.forEach((o) => { - assert.equal(o.get('z'), o.get('parent').get('y')); - assert.equal(o.get('z'), o.get('parent').get('child').get('x')); + Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query('Grandparent'); + q.equalTo('nested', true); + q.include('parent.child'); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 5); + results.forEach(o => { + assert.equal(o.get('z'), o.get('parent').get('y')); + assert.equal(o.get('z'), o.get('parent').get('child').get('x')); + }); + done(); }); - done(); - }); }); - it('can include without changing dirty', (done) => { + it('can include without changing dirty', done => { const parent = new Parse.Object('ParentObject'); const child = new Parse.Object('ChildObject'); parent.set('child', child); child.set('foo', 'bar'); - Parse.Object.saveAll([child, parent]).then(() => { - const query = new Parse.Query('ParentObject'); - query.include('child'); - query.equalTo('objectId', parent.id); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); - assert.equal(child.id, childAgain.id); - assert.equal(parent.id, parentAgain.id); - assert.equal(childAgain.get('foo'), 'bar'); - assert(!parentAgain.dirty()); - assert(!childAgain.dirty()); - done(); - }); + Parse.Object.saveAll([child, parent]) + .then(() => { + const query = new Parse.Query('ParentObject'); + query.include('child'); + query.equalTo('objectId', parent.id); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const parentAgain = results[0]; + const childAgain = parentAgain.get('child'); + assert.equal(child.id, childAgain.id); + assert.equal(parent.id, parentAgain.id); + assert.equal(childAgain.get('foo'), 'bar'); + assert(!parentAgain.dirty()); + assert(!childAgain.dirty()); + done(); + }); }); it('can exclude keys', async () => { @@ -1365,98 +1581,108 @@ describe('Parse Query', () => { assert.equal(result.get('slice'), 'pizza'); }); - it('uses subclasses when creating objects', (done) => { + it('uses subclasses when creating objects', done => { const ParentObject = Parse.Object.extend({ className: 'ParentObject' }); let ChildObject = Parse.Object.extend('ChildObject', { foo() { return 'foo'; - } + }, }); const parent = new ParentObject(); const child = new ChildObject(); parent.set('child', child); - Parse.Object.saveAll([child, parent]).then(() => { - ChildObject = Parse.Object.extend('ChildObject', { - bar() { - return 'bar'; - } + Parse.Object.saveAll([child, parent]) + .then(() => { + ChildObject = Parse.Object.extend('ChildObject', { + bar() { + return 'bar'; + }, + }); + + const query = new Parse.Query(ParentObject); + query.equalTo('objectId', parent.id); + query.include('child'); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + const parentAgain = results[0]; + const childAgain = parentAgain.get('child'); + assert.equal(childAgain.foo(), 'foo'); + assert.equal(childAgain.bar(), 'bar'); + done(); }); - - const query = new Parse.Query(ParentObject); - query.equalTo('objectId', parent.id); - query.include('child'); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - const parentAgain = results[0]; - const childAgain = parentAgain.get('child'); - assert.equal(childAgain.foo(), 'foo'); - assert.equal(childAgain.bar(), 'bar'); - done(); - }); }); - it('can match the results of another query', (done) => { + it('can match the results of another query', done => { const ParentObject = Parse.Object.extend('ParentObject'); const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { - objects.push(new ParentObject({ - child: new ChildObject({x: i, qtest: true}), - x: 10 + i, - })); + objects.push( + new ParentObject({ + child: new ChildObject({ x: i, qtest: true }), + x: 10 + i, + }) + ); } - Parse.Object.saveAll(objects).then(() => { - const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('qtest', true); - subQuery.greaterThan('x', 5); - const q = new Parse.Query(ParentObject); - q.matchesQuery('child', subQuery); - return q.find(); - }).then((results) => { - assert.equal(results.length, 4); - results.forEach((o) => { - assert(o.get('x') > 15); + Parse.Object.saveAll(objects) + .then(() => { + const subQuery = new Parse.Query(ChildObject); + subQuery.equalTo('qtest', true); + subQuery.greaterThan('x', 5); + const q = new Parse.Query(ParentObject); + q.matchesQuery('child', subQuery); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 4); + results.forEach(o => { + assert(o.get('x') > 15); + }); + done(); }); - done(); - }); }); - it('can not match the results of another query', (done) => { + it('can not match the results of another query', done => { const ParentObject = Parse.Object.extend('ParentObject'); const ChildObject = Parse.Object.extend('ChildObject'); const objects = []; for (let i = 0; i < 10; i++) { - objects.push(new ParentObject({ - child: new ChildObject({x: i, dneqtest: true}), - dneqtest: true, - x: 10 + i, - })); + objects.push( + new ParentObject({ + child: new ChildObject({ x: i, dneqtest: true }), + dneqtest: true, + x: 10 + i, + }) + ); } - Parse.Object.saveAll(objects).then(() => { - const subQuery = new Parse.Query(ChildObject); - subQuery.equalTo('dneqtest', true); - subQuery.greaterThan('x', 5); - const q = new Parse.Query(ParentObject); - q.equalTo('dneqtest', true); - q.doesNotMatchQuery('child', subQuery); - return q.find(); - }).then((results) => { - assert.equal(results.length, 6); - results.forEach((o) => { - assert(o.get('x') >= 10); - assert(o.get('x') <= 15); - }); - done(); - }) + Parse.Object.saveAll(objects) + .then(() => { + const subQuery = new Parse.Query(ChildObject); + subQuery.equalTo('dneqtest', true); + subQuery.greaterThan('x', 5); + const q = new Parse.Query(ParentObject); + q.equalTo('dneqtest', true); + q.doesNotMatchQuery('child', subQuery); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 6); + results.forEach(o => { + assert(o.get('x') >= 10); + assert(o.get('x') <= 15); + }); + done(); + }) .catch(err => { console.dir(err); done.fail(); }); }); - it('can select keys from a matched query', (done) => { + it('can select keys from a matched query', done => { const Restaurant = Parse.Object.extend('Restaurant'); const Person = Parse.Object.extend('Person'); const objects = [ @@ -1467,87 +1693,98 @@ describe('Parse Query', () => { new Person({ name: 'Billy', hometown: 'Detroit' }), ]; - Parse.Object.saveAll(objects).then(() => { - const query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); - const mainQuery = new Parse.Query(Person); - mainQuery.matchesKeyInQuery('hometown', 'location', query); - return mainQuery.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('name'), 'Bob'); - - const query = new Parse.Query(Restaurant); - query.greaterThan('rating', 4); - const mainQuery = new Parse.Query(Person); - mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); - mainQuery.ascending('name'); - return mainQuery.find(); - }).then((results) => { - assert.equal(results.length, 2); - assert.equal(results[0].get('name'), 'Billy'); - assert.equal(results[1].get('name'), 'Tom'); - - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const query = new Parse.Query(Restaurant); + query.greaterThan('rating', 4); + const mainQuery = new Parse.Query(Person); + mainQuery.matchesKeyInQuery('hometown', 'location', query); + return mainQuery.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('name'), 'Bob'); + + const query = new Parse.Query(Restaurant); + query.greaterThan('rating', 4); + const mainQuery = new Parse.Query(Person); + mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); + mainQuery.ascending('name'); + return mainQuery.find(); + }) + .then(results => { + assert.equal(results.length, 2); + assert.equal(results[0].get('name'), 'Billy'); + assert.equal(results[1].get('name'), 'Tom'); + + done(); + }); }); - it('supports objects with length', (done) => { + it('supports objects with length', done => { const obj = new TestObject(); obj.set('length', 5); assert.equal(obj.get('length'), 5); - obj.save().then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('objectId', obj.id); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('length'), 5); - done(); - }); + obj + .save() + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('objectId', obj.id); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('length'), 5); + done(); + }); }); - it('can include User fields', (done) => { - Parse.User.signUp('bob', 'password', { age: 21 }).then((user) => { - const obj = new TestObject(); - return obj.save({ owner: user }); - }).then((obj) => { - const query = new Parse.Query(TestObject); - query.include('owner'); - return query.get(obj.id); - }).then((objAgain) => { - assert(objAgain.get('owner') instanceof Parse.User); - assert.equal(objAgain.get('owner').get('age'), 21); - done(); - }); + it('can include User fields', done => { + Parse.User.signUp('bob', 'password', { age: 21 }) + .then(user => { + const obj = new TestObject(); + return obj.save({ owner: user }); + }) + .then(obj => { + const query = new Parse.Query(TestObject); + query.include('owner'); + return query.get(obj.id); + }) + .then(objAgain => { + assert(objAgain.get('owner') instanceof Parse.User); + assert.equal(objAgain.get('owner').get('age'), 21); + done(); + }); }); - it('can build OR queries', (done) => { + it('can build OR queries', done => { const objects = []; for (let i = 0; i < 10; i++) { const obj = new Parse.Object('BoxedNumber'); obj.set({ x: i, orquery: true }); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('orquery', true); - q1.lessThan('x', 2); - const q2 = new Parse.Query('BoxedNumber'); - q2.equalTo('orquery', true); - q2.greaterThan('x', 5); - const orQuery = Parse.Query.or(q1, q2); - return orQuery.find(); - }).then((results) => { - assert.equal(results.length, 6); - results.forEach((number) => { - assert(number.get('x') < 2 || number.get('x') > 5); + Parse.Object.saveAll(objects) + .then(() => { + const q1 = new Parse.Query('BoxedNumber'); + q1.equalTo('orquery', true); + q1.lessThan('x', 2); + const q2 = new Parse.Query('BoxedNumber'); + q2.equalTo('orquery', true); + q2.greaterThan('x', 5); + const orQuery = Parse.Query.or(q1, q2); + return orQuery.find(); + }) + .then(results => { + assert.equal(results.length, 6); + results.forEach(number => { + assert(number.get('x') < 2 || number.get('x') > 5); + }); + done(); }); - done(); - }); }); - it('can build complex OR queries', (done) => { + it('can build complex OR queries', done => { const objects = []; for (let i = 0; i < 10; i++) { const child = new Parse.Object('Child'); @@ -1559,49 +1796,55 @@ describe('Parse Query', () => { parent.set('y', i); objects.push(parent); } - Parse.Object.saveAll(objects).then(() => { - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('complexor', true); - const q1 = new Parse.Query('Parent'); - q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('complexor', true); - q2.lessThan('y', 2); - const orQuery = Parse.Query.or(q1, q2); - return orQuery.find(); - }).then((results) => { - assert.equal(results.length, 3); - done(); - }).catch(done.fail); - }); - - it('can build AND queries', (done) => { + Parse.Object.saveAll(objects) + .then(() => { + const subQuery = new Parse.Query('Child'); + subQuery.equalTo('x', 4); + subQuery.equalTo('complexor', true); + const q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); + const q2 = new Parse.Query('Parent'); + q2.equalTo('complexor', true); + q2.lessThan('y', 2); + const orQuery = Parse.Query.or(q1, q2); + return orQuery.find(); + }) + .then(results => { + assert.equal(results.length, 3); + done(); + }) + .catch(done.fail); + }); + + it('can build AND queries', done => { const objects = []; for (let i = 0; i < 10; i++) { const obj = new Parse.Object('BoxedNumber'); obj.set({ x: i, and: true }); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const q1 = new Parse.Query('BoxedNumber'); - q1.equalTo('and', true); - q1.greaterThan('x', 2); - const q2 = new Parse.Query('BoxedNumber'); - q2.equalTo('and', true); - q2.lessThan('x', 5); - const andQuery = Parse.Query.and(q1, q2); - return andQuery.find(); - }).then((results) => { - assert.equal(results.length, 2); - results.forEach((number) => { - assert(number.get('x') > 2 && number.get('x') < 5); - }); - done(); - }).catch(e => console.log(e)); - }); - - it('can build complex AND queries', (done) => { + Parse.Object.saveAll(objects) + .then(() => { + const q1 = new Parse.Query('BoxedNumber'); + q1.equalTo('and', true); + q1.greaterThan('x', 2); + const q2 = new Parse.Query('BoxedNumber'); + q2.equalTo('and', true); + q2.lessThan('x', 5); + const andQuery = Parse.Query.and(q1, q2); + return andQuery.find(); + }) + .then(results => { + assert.equal(results.length, 2); + results.forEach(number => { + assert(number.get('x') > 2 && number.get('x') < 5); + }); + done(); + }) + .catch(e => console.log(e)); + }); + + it('can build complex AND queries', done => { const objects = []; for (let i = 0; i < 10; i++) { const child = new Parse.Object('Child'); @@ -1613,21 +1856,24 @@ describe('Parse Query', () => { parent.set('y', i); objects.push(parent); } - Parse.Object.saveAll(objects).then(() => { - const subQuery = new Parse.Query('Child'); - subQuery.equalTo('x', 4); - subQuery.equalTo('and', true); - const q1 = new Parse.Query('Parent'); - q1.matchesQuery('child', subQuery); - const q2 = new Parse.Query('Parent'); - q2.equalTo('and', true); - q2.equalTo('y', 4); - const andQuery = Parse.Query.and(q1, q2); - return andQuery.find(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }).catch(done.fail); + Parse.Object.saveAll(objects) + .then(() => { + const subQuery = new Parse.Query('Child'); + subQuery.equalTo('x', 4); + subQuery.equalTo('and', true); + const q1 = new Parse.Query('Parent'); + q1.matchesQuery('child', subQuery); + const q2 = new Parse.Query('Parent'); + q2.equalTo('and', true); + q2.equalTo('y', 4); + const andQuery = Parse.Query.and(q1, q2); + return andQuery.find(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }) + .catch(done.fail); }); it('can build NOR queries', async () => { @@ -1647,7 +1893,7 @@ describe('Parse Query', () => { const results = await norQuery.find(); assert.equal(results.length, 3); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') >= 3 && number.get('x') <= 5); }); }); @@ -1674,126 +1920,140 @@ describe('Parse Query', () => { const results = await norQuery.find(); assert.equal(results.length, 8); - results.forEach((number) => { + results.forEach(number => { assert(number.get('x') !== 4 || number.get('x') !== 5); }); }); - it('can iterate over results with each', (done) => { + it('can iterate over results with each', done => { const items = []; for (let i = 0; i < 50; i++) { items.push(new TestObject({ x: i, eachtest: true })); } const seen = []; - Parse.Object.saveAll(items).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - - return query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + Parse.Object.saveAll(items) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('eachtest', true); + query.lessThan('x', 25); + + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + }); + }) + .then(() => { + assert.equal(seen.length, 25); + for (let i = 0; i < seen.length; i++) { + assert.equal(seen[i], 1); + } + done(); }); - }).then(() => { - assert.equal(seen.length, 25); - for (let i = 0; i < seen.length; i++) { - assert.equal(seen[i], 1); - } - done(); - }); }); - it('fails query.each with order', (done) => { + it('fails query.each with order', done => { const items = []; for (let i = 0; i < 50; i++) { items.push(new TestObject({ x: i, eachtest: true })); } const seen = []; - Parse.Object.saveAll(items).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - query.ascending('x'); - - return query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + Parse.Object.saveAll(items) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('eachtest', true); + query.lessThan('x', 25); + query.ascending('x'); + + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + }); + }) + .then(null, () => { + done(); }); - }).then(null, () => { - done(); - }); }); - it('fails query.each with limit', (done) => { + it('fails query.each with limit', done => { const items = []; for (let i = 0; i < 50; i++) { items.push(new TestObject({ x: i, eachtest: true })); } const seen = []; - Parse.Object.saveAll(items).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - query.limit(20); - - return query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + Parse.Object.saveAll(items) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('eachtest', true); + query.lessThan('x', 25); + query.limit(20); + + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + }); + }) + .then(null, () => { + done(); }); - }).then(null, () => { - done(); - }); }); - it('fails query.each with skip', (done) => { + it('fails query.each with skip', done => { const items = []; for (let i = 0; i < 50; i++) { items.push(new TestObject({ x: i, eachtest: true })); } const seen = []; - Parse.Object.saveAll(items).then(() => { - const query = new Parse.Query(TestObject); - query.equalTo('eachtest', true); - query.lessThan('x', 25); - query.skip(20); - - return query.each((obj) => { - seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + Parse.Object.saveAll(items) + .then(() => { + const query = new Parse.Query(TestObject); + query.equalTo('eachtest', true); + query.lessThan('x', 25); + query.skip(20); + + return query.each(obj => { + seen[obj.get('x')] = (seen[obj.get('x')] || 0) + 1; + }); + }) + .then(null, () => { + done(); }); - }).then(null, () => { - done(); - }); }); - it('can select specific keys', (done) => { + it('can select specific keys', done => { const obj = new TestObject({ foo: 'baz', bar: 1 }); - obj.save().then(() => { - const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); - return q.first(); - }).then((result) => { - assert(result.id); - assert(result.createdAt); - assert(result.updatedAt); - assert(!result.dirty()); - assert.equal(result.get('foo'), 'baz'); - assert.equal(result.get('bar'), undefined); - done(); - }); + obj + .save() + .then(() => { + const q = new Parse.Query(TestObject); + q.equalTo('objectId', obj.id); + q.select('foo'); + return q.first(); + }) + .then(result => { + assert(result.id); + assert(result.createdAt); + assert(result.updatedAt); + assert(!result.dirty()); + assert.equal(result.get('foo'), 'baz'); + assert.equal(result.get('bar'), undefined); + done(); + }); }); - it('can select specific keys with each', (done) => { + it('can select specific keys with each', done => { const obj = new TestObject({ foo: 'baz', bar: 1 }); - obj.save().then(() => { - const q = new Parse.Query(TestObject); - q.equalTo('objectId', obj.id); - q.select('foo'); - return q.each((o) => { - assert(o.id); - assert.equal(o.get('foo'), 'baz'); - assert.equal(o.get('bar'), undefined); + obj + .save() + .then(() => { + const q = new Parse.Query(TestObject); + q.equalTo('objectId', obj.id); + q.select('foo'); + return q.each(o => { + assert(o.id); + assert.equal(o.get('foo'), 'baz'); + assert.equal(o.get('bar'), undefined); + }); + }) + .then(() => { + done(); }); - }).then(() => { - done(); - }); }); it('can perform a full text search', () => { @@ -1812,13 +2072,15 @@ describe('Parse Query', () => { const obj = new TestObject({ subject: subjects[i] }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestObject); - q.fullText('subject', 'coffee'); - return q.find(); - }).then((results) => { - assert.equal(results.length, 3); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestObject); + q.fullText('subject', 'coffee'); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 3); + }); }); it('can perform a full text search sort', () => { @@ -1837,21 +2099,22 @@ describe('Parse Query', () => { const obj = new TestObject({ subject: subjects[i] }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestObject); - q.fullText('subject', 'coffee'); - q.ascending('$score'); - q.select('$score'); - return q.find(); - }).then((results) => { - assert.equal(results.length, 3); - assert.equal(results[0].get('score'), 1); - assert.equal(results[1].get('score'), 0.75); - assert.equal(results[2].get('score'), 0.75); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestObject); + q.fullText('subject', 'coffee'); + q.ascending('$score'); + q.select('$score'); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 3); + assert.equal(results[0].get('score'), 1); + assert.equal(results[1].get('score'), 0.75); + assert.equal(results[2].get('score'), 0.75); + }); }); - it('can perform a full text search with language options', () => { const subjects = [ 'café', @@ -1869,13 +2132,15 @@ describe('Parse Query', () => { const obj = new TestLanguageOption({ language_comment: subjects[i] }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestLanguageOption); - q.fullText('language_comment', 'preparar', { language: 'portuguese' }); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestLanguageOption); + q.fullText('language_comment', 'preparar', { language: 'portuguese' }); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + }); }); it('can perform a full text search with case sensitive options', () => { @@ -1895,13 +2160,17 @@ describe('Parse Query', () => { const obj = new TestCaseOption({ casesensitive_comment: subjects[i] }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestCaseOption); - q.fullText('casesensitive_comment', 'Preparar', { caseSensitive: true }); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestCaseOption); + q.fullText('casesensitive_comment', 'Preparar', { + caseSensitive: true, + }); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + }); }); it('can perform a full text search with diacritic sensitive options', () => { @@ -1921,39 +2190,43 @@ describe('Parse Query', () => { const obj = new TestDiacriticOption({ diacritic_comment: subjects[i] }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestDiacriticOption); - q.fullText('diacritic_comment', 'cafe', { diacriticSensitive: true }); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestDiacriticOption); + q.fullText('diacritic_comment', 'cafe', { diacriticSensitive: true }); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + }); }); it('can perform a full text search with case and diacritic sensitive options', () => { - const subjects = [ - 'Café', - 'café', - 'preparar Cafe e creme', - 'preparação de cafe com leite', - ]; + const subjects = ['Café', 'café', 'preparar Cafe e creme', 'preparação de cafe com leite']; const TestCaseDiacriticOption = Parse.Object.extend('TestCaseDiacriticOption'); const objects = []; for (const i in subjects) { - const obj = new TestCaseDiacriticOption({ diacritic_comment: subjects[i] }); + const obj = new TestCaseDiacriticOption({ + diacritic_comment: subjects[i], + }); objects.push(obj); } - return Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestCaseDiacriticOption); - q.fullText('diacritic_comment', 'cafe', { caseSensitive: true, diacriticSensitive: true }); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('diacritic_comment'), 'preparação de cafe com leite'); - }); + return Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestCaseDiacriticOption); + q.fullText('diacritic_comment', 'cafe', { + caseSensitive: true, + diacriticSensitive: true, + }); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('diacritic_comment'), 'preparação de cafe com leite'); + }); }); - it('fails to perform a full text search with unknown options', (done) => { + it('fails to perform a full text search with unknown options', done => { const subjects = [ 'café', 'loja de café', @@ -1969,13 +2242,18 @@ describe('Parse Query', () => { const obj = new TestObject({ comment: subjects[i] }); objects.push(obj); } - Parse.Object.saveAll(objects).then(() => { - const q = new Parse.Query(TestObject); - q.fullText('comment', 'preparar', { language: "portuguese", notAnOption: true }); - return q.find(); - }).catch(() => { - done(); - }); + Parse.Object.saveAll(objects) + .then(() => { + const q = new Parse.Query(TestObject); + q.fullText('comment', 'preparar', { + language: 'portuguese', + notAnOption: true, + }); + return q.find(); + }) + .catch(() => { + done(); + }); }); it('can return results in map', async () => { @@ -2036,7 +2314,7 @@ describe('Parse Query', () => { await Parse.Object.saveAll([obj1, obj2, obj3]); const query = new Parse.Query(TestObject); - query.find().then((results) => { + query.find().then(results => { assert.equal(results.length, 0); }); query.cancel(); diff --git a/integration/test/ParseRelationTest.js b/integration/test/ParseRelationTest.js index 9c1915d11..05fbeb193 100644 --- a/integration/test/ParseRelationTest.js +++ b/integration/test/ParseRelationTest.js @@ -7,7 +7,7 @@ const Parse = require('../../node'); const TestObject = Parse.Object.extend('TestObject'); describe('Parse Relation', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); @@ -16,202 +16,229 @@ describe('Parse Relation', () => { }); }); - it('can do a simple add and remove', (done) => { + it('can do a simple add and remove', done => { const ChildObject = Parse.Object.extend('ChildObject'); const childObjects = []; for (let i = 0; i < 10; i++) { - childObjects.push(new ChildObject({x: i})); + childObjects.push(new ChildObject({ x: i })); } let rel = null; let parent = null; - Parse.Object.saveAll(childObjects).then(() => { - parent = new Parse.Object('ParentObject'); - parent.set('x', 4); - rel = parent.relation('child'); - rel.add(childObjects[0]); - return parent.save(); - }).then((parentAgain) => { - assert(!parent.dirty('child')); - assert(!parentAgain.dirty('child')); - return rel.query().find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].id, childObjects[0].id); - - rel.remove(childObjects[0]); - return parent.save(); - }).then((parentAgain) => { - assert(!parent.dirty('child')); - assert(!parentAgain.dirty('child')); - return rel.query().find(); - }).then((results) => { - assert.equal(results.length, 0); - done(); - }); + Parse.Object.saveAll(childObjects) + .then(() => { + parent = new Parse.Object('ParentObject'); + parent.set('x', 4); + rel = parent.relation('child'); + rel.add(childObjects[0]); + return parent.save(); + }) + .then(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); + return rel.query().find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].id, childObjects[0].id); + + rel.remove(childObjects[0]); + return parent.save(); + }) + .then(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); + return rel.query().find(); + }) + .then(results => { + assert.equal(results.length, 0); + done(); + }); }); - it('can query relation without schema', (done) => { + it('can query relation without schema', done => { const ChildObject = Parse.Object.extend('ChildObject'); const childObjects = []; for (let i = 0; i < 10; i++) { - childObjects.push(new ChildObject({x: i})); + childObjects.push(new ChildObject({ x: i })); } let parent = null; - Parse.Object.saveAll(childObjects).then(() => { - parent = new Parse.Object('ParentObject'); - parent.set('x', 4); - const rel = parent.relation('child'); - rel.add(childObjects[0]); - return parent.save(); - }).then((parentAgain) => { - assert(!parent.dirty('child')); - assert(!parentAgain.dirty('child')); - return parentAgain.relation('child').query().find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].id, childObjects[0].id); - done(); - }); + Parse.Object.saveAll(childObjects) + .then(() => { + parent = new Parse.Object('ParentObject'); + parent.set('x', 4); + const rel = parent.relation('child'); + rel.add(childObjects[0]); + return parent.save(); + }) + .then(parentAgain => { + assert(!parent.dirty('child')); + assert(!parentAgain.dirty('child')); + return parentAgain.relation('child').query().find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].id, childObjects[0].id); + done(); + }); }); - it('can compound add and remove operations', (done) => { + it('can compound add and remove operations', done => { const ChildObject = Parse.Object.extend('ChildObject'); const childObjects = []; for (let i = 0; i < 10; i++) { - childObjects.push(new ChildObject({x: i})); + childObjects.push(new ChildObject({ x: i })); } let parent = null; let rel = null; - Parse.Object.saveAll(childObjects).then(() => { - parent = new Parse.Object('ParentObject'); - parent.set('x', 4); - rel = parent.relation('child'); - rel.add(childObjects[0]); - rel.add(childObjects[1]); - rel.remove(childObjects[0]); - rel.add(childObjects[2]); - return parent.save(); - }).then(() => { - return rel.query().find(); - }).then((results) => { - assert.equal(results.length, 2); - - rel.remove(childObjects[1]); - rel.remove(childObjects[2]); - rel.add(childObjects[1]); - rel.add(childObjects[0]); - - return parent.save(); - }).then(() => { - return rel.query().find(); - }).then((results) => { - assert.equal(results.length, 2); - done(); - }); + Parse.Object.saveAll(childObjects) + .then(() => { + parent = new Parse.Object('ParentObject'); + parent.set('x', 4); + rel = parent.relation('child'); + rel.add(childObjects[0]); + rel.add(childObjects[1]); + rel.remove(childObjects[0]); + rel.add(childObjects[2]); + return parent.save(); + }) + .then(() => { + return rel.query().find(); + }) + .then(results => { + assert.equal(results.length, 2); + + rel.remove(childObjects[1]); + rel.remove(childObjects[2]); + rel.add(childObjects[1]); + rel.add(childObjects[0]); + + return parent.save(); + }) + .then(() => { + return rel.query().find(); + }) + .then(results => { + assert.equal(results.length, 2); + done(); + }); }); - it('can refine relation queries', (done) => { + it('can refine relation queries', done => { const ChildObject = Parse.Object.extend('ChildObject'); const childObjects = []; for (let i = 0; i < 10; i++) { - childObjects.push(new ChildObject({x: i})); + childObjects.push(new ChildObject({ x: i })); } - Parse.Object.saveAll(childObjects).then(() => { - const parent = new Parse.Object('ParentObject'); - parent.set('x', 4); - const rel = parent.relation('child'); - rel.add(childObjects[0]); - rel.add(childObjects[1]); - rel.add(childObjects[2]); - return parent.save(); - }).then((parentAgain) => { - const q = parentAgain.relation('child').query(); - q.equalTo('x', 2); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].id, childObjects[2].id); - done(); - }); + Parse.Object.saveAll(childObjects) + .then(() => { + const parent = new Parse.Object('ParentObject'); + parent.set('x', 4); + const rel = parent.relation('child'); + rel.add(childObjects[0]); + rel.add(childObjects[1]); + rel.add(childObjects[2]); + return parent.save(); + }) + .then(parentAgain => { + const q = parentAgain.relation('child').query(); + q.equalTo('x', 2); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].id, childObjects[2].id); + done(); + }); }); - it('can query relation fields', (done) => { + it('can query relation fields', done => { const ChildObject = Parse.Object.extend('ChildObject'); const childObjects = []; for (let i = 0; i < 10; i++) { - childObjects.push(new ChildObject({x: i})); + childObjects.push(new ChildObject({ x: i })); } - Parse.Object.saveAll(childObjects).then(() => { - const parent = new Parse.Object('ParentObject'); - parent.set('x', 4); - const rel = parent.relation('child'); - rel.add(childObjects[0]); - rel.add(childObjects[1]); - rel.add(childObjects[2]); - const parent2 = new Parse.Object('ParentObject'); - parent2.set('x', 3); - const rel2 = parent2.relation('child'); - rel2.add(childObjects[4]); - rel2.add(childObjects[5]); - rel2.add(childObjects[6]); - return Parse.Object.saveAll([parent, parent2]); - }).then(() => { - const q = new Parse.Query('ParentObject'); - const objects = [childObjects[4], childObjects[9]]; - q.containedIn('child', objects); - return q.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].get('x'), 3); - done(); - }); + Parse.Object.saveAll(childObjects) + .then(() => { + const parent = new Parse.Object('ParentObject'); + parent.set('x', 4); + const rel = parent.relation('child'); + rel.add(childObjects[0]); + rel.add(childObjects[1]); + rel.add(childObjects[2]); + const parent2 = new Parse.Object('ParentObject'); + parent2.set('x', 3); + const rel2 = parent2.relation('child'); + rel2.add(childObjects[4]); + rel2.add(childObjects[5]); + rel2.add(childObjects[6]); + return Parse.Object.saveAll([parent, parent2]); + }) + .then(() => { + const q = new Parse.Query('ParentObject'); + const objects = [childObjects[4], childObjects[9]]; + q.containedIn('child', objects); + return q.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].get('x'), 3); + done(); + }); }); - it('can get a query on a relation when the parent is unfetched', (done) => { + it('can get a query on a relation when the parent is unfetched', done => { const Wheel = Parse.Object.extend('Wheel'); const Car = Parse.Object.extend('Car'); const origWheel = new Wheel(); - origWheel.save().then(() => { - const car = new Car(); - const relation = car.relation('wheels'); - relation.add(origWheel); - return car.save(); - }).then((car) => { - const unfetchedCar = new Car(); - unfetchedCar.id = car.id; - const relation = unfetchedCar.relation('wheels'); - const query = relation.query(); - - return query.get(origWheel.id); - }).then((wheel) => { - assert.equal(wheel.className, 'Wheel'); - assert.equal(wheel.id, origWheel.id); - done(); - }); + origWheel + .save() + .then(() => { + const car = new Car(); + const relation = car.relation('wheels'); + relation.add(origWheel); + return car.save(); + }) + .then(car => { + const unfetchedCar = new Car(); + unfetchedCar.id = car.id; + const relation = unfetchedCar.relation('wheels'); + const query = relation.query(); + + return query.get(origWheel.id); + }) + .then(wheel => { + assert.equal(wheel.className, 'Wheel'); + assert.equal(wheel.id, origWheel.id); + done(); + }); }); - it('can find a query on a relation when the parent is unfetched', (done) => { + it('can find a query on a relation when the parent is unfetched', done => { const Wheel = Parse.Object.extend('Wheel'); const Car = Parse.Object.extend('Car'); const origWheel = new Wheel(); - origWheel.save().then(() => { - const car = new Car(); - const relation = car.relation('wheels'); - relation.add(origWheel); - return car.save(); - }).then((car) => { - const unfetchedCar = new Car(); - unfetchedCar.id = car.id; - const relation = unfetchedCar.relation('wheels'); - const query = relation.query(); - - return query.find(); - }).then((wheels) => { - assert.equal(wheels.length, 1); - assert.equal(wheels[0].className, 'Wheel'); - assert.equal(wheels[0].id, origWheel.id); - done(); - }); + origWheel + .save() + .then(() => { + const car = new Car(); + const relation = car.relation('wheels'); + relation.add(origWheel); + return car.save(); + }) + .then(car => { + const unfetchedCar = new Car(); + unfetchedCar.id = car.id; + const relation = unfetchedCar.relation('wheels'); + const query = relation.query(); + + return query.find(); + }) + .then(wheels => { + assert.equal(wheels.length, 1); + assert.equal(wheels[0].className, 'Wheel'); + assert.equal(wheels[0].id, origWheel.id); + done(); + }); }); it('can add empty array to relation', async () => { diff --git a/integration/test/ParseSchemaTest.js b/integration/test/ParseSchemaTest.js index ab07e95f9..dfa48a240 100644 --- a/integration/test/ParseSchemaTest.js +++ b/integration/test/ParseSchemaTest.js @@ -34,32 +34,37 @@ describe('Schema', () => { Parse.Storage._clear(); }); - beforeEach((done) => { + beforeEach(done => { clear().then(done); }); - it('invalid get all no schema', (done) => { - Parse.Schema.all().then(() => {}).catch(() => { - done(); - }); + it('invalid get all no schema', done => { + Parse.Schema.all() + .then(() => {}) + .catch(() => { + done(); + }); }); - it('invalid get no schema', (done) => { + it('invalid get no schema', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.get().then(() => {}).catch(() => { - done(); - }); + testSchema + .get() + .then(() => {}) + .catch(() => { + done(); + }); }); - it('save', (done) => { + it('save', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then((result) => { + testSchema.save().then(result => { assert.equal(result.className, 'SchemaTest'); done(); }); }); - it('get', (done) => { + it('get', done => { const testSchema = new Parse.Schema('SchemaTest'); testSchema .addField('defaultFieldString') @@ -75,44 +80,55 @@ describe('Schema', () => { .addPointer('pointerField', '_User') .addRelation('relationField', '_User'); - testSchema.save().then(() => { - return testSchema.get(); - }).then((result) => { - assert.equal(result.fields.defaultFieldString.type, 'String'); - assert.equal(result.fields.stringField.type, 'String'); - assert.equal(result.fields.numberField.type, 'Number'); - assert.equal(result.fields.booleanField.type, 'Boolean'); - assert.equal(result.fields.dateField.type, 'Date'); - assert.equal(result.fields.fileField.type, 'File'); - assert.equal(result.fields.geoPointField.type, 'GeoPoint'); - assert.equal(result.fields.polygonField.type, 'Polygon'); - assert.equal(result.fields.arrayField.type, 'Array'); - assert.equal(result.fields.objectField.type, 'Object'); - assert.equal(result.fields.pointerField.type, 'Pointer'); - assert.equal(result.fields.relationField.type, 'Relation'); - assert.equal(result.fields.pointerField.targetClass, '_User'); - assert.equal(result.fields.relationField.targetClass, '_User'); - done(); - }); + testSchema + .save() + .then(() => { + return testSchema.get(); + }) + .then(result => { + assert.equal(result.fields.defaultFieldString.type, 'String'); + assert.equal(result.fields.stringField.type, 'String'); + assert.equal(result.fields.numberField.type, 'Number'); + assert.equal(result.fields.booleanField.type, 'Boolean'); + assert.equal(result.fields.dateField.type, 'Date'); + assert.equal(result.fields.fileField.type, 'File'); + assert.equal(result.fields.geoPointField.type, 'GeoPoint'); + assert.equal(result.fields.polygonField.type, 'Polygon'); + assert.equal(result.fields.arrayField.type, 'Array'); + assert.equal(result.fields.objectField.type, 'Object'); + assert.equal(result.fields.pointerField.type, 'Pointer'); + assert.equal(result.fields.relationField.type, 'Relation'); + assert.equal(result.fields.pointerField.targetClass, '_User'); + assert.equal(result.fields.relationField.targetClass, '_User'); + done(); + }); }); - it('all', (done) => { + it('all', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then(() => { - return Parse.Schema.all(); - }).then((results) => { - assert.equal(results.length, 1); - done(); - }); + testSchema + .save() + .then(() => { + return Parse.Schema.all(); + }) + .then(results => { + assert.equal(results.length, 1); + done(); + }); }); it('save required and default values', async () => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.addField('fieldString', 'String', { required: true, defaultValue: 'Hello World' }); + testSchema.addField('fieldString', 'String', { + required: true, + defaultValue: 'Hello World', + }); const schema = await testSchema.save(); assert.deepEqual(schema.fields.fieldString, { - type: 'String', required: true, defaultValue: 'Hello World' - }) + type: 'String', + required: true, + defaultValue: 'Hello World', + }); const object = new Parse.Object('SchemaTest'); await object.save(); assert.equal(object.get('fieldString'), 'Hello World'); @@ -123,8 +139,14 @@ describe('Schema', () => { await pointer.save(); const testSchema = new Parse.Schema('SchemaTest'); testSchema - .addPointer('pointerField', 'TestObject', { required: true, defaultValue: pointer }) - .addPointer('pointerJSONField', 'TestObject', { required: true, defaultValue: pointer.toPointer() }) + .addPointer('pointerField', 'TestObject', { + required: true, + defaultValue: pointer, + }) + .addPointer('pointerJSONField', 'TestObject', { + required: true, + defaultValue: pointer.toPointer(), + }); const schema = await testSchema.save(); assert.deepEqual(schema.fields.pointerField, schema.fields.pointerJSONField); assert.deepEqual(schema.fields.pointerField.defaultValue, pointer.toPointer()); @@ -133,41 +155,82 @@ describe('Schema', () => { it('set multiple required and default values', async () => { const point = new Parse.GeoPoint(44.0, -11.0); - const polygon = new Parse.Polygon([[0,0], [0,1], [1,1], [1,0]]); + const polygon = new Parse.Polygon([ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]); const file = new Parse.File('parse-server-logo', { base64: 'ParseA==' }); await file.save(); const testSchema = new Parse.Schema('SchemaFieldTest'); testSchema - .addField('defaultFieldString', 'String', { required: true, defaultValue: 'hello' }) + .addField('defaultFieldString', 'String', { + required: true, + defaultValue: 'hello', + }) .addString('stringField', { required: true, defaultValue: 'world' }) .addNumber('numberField', { required: true, defaultValue: 10 }) .addBoolean('booleanField', { required: true, defaultValue: false }) - .addDate('dateField', { required: true, defaultValue: new Date('2000-01-01T00:00:00.000Z') }) - .addDate('dateStringField', { required: true, defaultValue: '2000-01-01T00:00:00.000Z' }) + .addDate('dateField', { + required: true, + defaultValue: new Date('2000-01-01T00:00:00.000Z'), + }) + .addDate('dateStringField', { + required: true, + defaultValue: '2000-01-01T00:00:00.000Z', + }) .addFile('fileField', { required: true, defaultValue: file }) .addGeoPoint('geoPointField', { required: true, defaultValue: point }) .addPolygon('polygonField', { required: true, defaultValue: polygon }) .addArray('arrayField', { required: true, defaultValue: [1, 2, 3] }) - .addObject('objectField', { required: true, defaultValue: { foo: 'bar' } }) + .addObject('objectField', { + required: true, + defaultValue: { foo: 'bar' }, + }); const schema = await testSchema.save(); assert.deepEqual(schema.fields, { objectId: { type: 'String' }, updatedAt: { type: 'Date' }, createdAt: { type: 'Date' }, - defaultFieldString: { type: 'String', required: true, defaultValue: 'hello' }, + defaultFieldString: { + type: 'String', + required: true, + defaultValue: 'hello', + }, stringField: { type: 'String', required: true, defaultValue: 'world' }, numberField: { type: 'Number', required: true, defaultValue: 10 }, booleanField: { type: 'Boolean', required: true, defaultValue: false }, - dateField: { type: 'Date', required: true, defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' } }, - dateStringField: { type: 'Date', required: true, defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' } }, + dateField: { + type: 'Date', + required: true, + defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, + }, + dateStringField: { + type: 'Date', + required: true, + defaultValue: { __type: 'Date', iso: '2000-01-01T00:00:00.000Z' }, + }, fileField: { type: 'File', required: true, defaultValue: file.toJSON() }, - geoPointField: { type: 'GeoPoint', required: true, defaultValue: point.toJSON() }, - polygonField: { type: 'Polygon', required: true, defaultValue: polygon.toJSON() }, + geoPointField: { + type: 'GeoPoint', + required: true, + defaultValue: point.toJSON(), + }, + polygonField: { + type: 'Polygon', + required: true, + defaultValue: polygon.toJSON(), + }, arrayField: { type: 'Array', required: true, defaultValue: [1, 2, 3] }, - objectField: { type: 'Object', required: true, defaultValue: { foo: 'bar' } }, - ACL: { type: 'ACL' } + objectField: { + type: 'Object', + required: true, + defaultValue: { foo: 'bar' }, + }, + ACL: { type: 'ACL' }, }); const object = new Parse.Object('SchemaFieldTest'); await object.save(); @@ -187,9 +250,15 @@ describe('Schema', () => { geoPointField: point.toJSON(), polygonField: { __type: 'Polygon', - coordinates: [ [ 0, 0 ], [ 0, 1 ], [ 1, 1 ], [ 1, 0 ], [ 0, 0 ] ] + coordinates: [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ], }, - arrayField: [ 1, 2, 3 ], + arrayField: [1, 2, 3], objectField: { foo: 'bar' }, }; assert.deepEqual(json, expected); @@ -204,7 +273,7 @@ describe('Schema', () => { update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; const testSchema = new Parse.Schema('SchemaTest'); testSchema.setCLP(clp); @@ -221,7 +290,7 @@ describe('Schema', () => { update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; const testSchema = new Parse.Schema('SchemaTest'); let schema = await testSchema.save(); @@ -249,7 +318,7 @@ describe('Schema', () => { update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; const testSchema = new Parse.Schema('SchemaTest'); testSchema.setCLP(clp); @@ -263,130 +332,163 @@ describe('Schema', () => { assert.deepEqual(schema.classLevelPermissions, clp); }); - it('update', (done) => { + it('update', done => { const testSchema = new Parse.Schema('SchemaTest'); testSchema.addString('name'); - testSchema.save().then(() => { - testSchema.deleteField('name'); - testSchema.addNumber('quantity'); - testSchema.addBoolean('status'); - return testSchema.update(); - }).then((result) => { - assert.equal(result.fields.status.type, 'Boolean'); - assert.equal(result.fields.quantity.type, 'Number'); - assert.equal(result.fields.name, undefined); - done(); - }); + testSchema + .save() + .then(() => { + testSchema.deleteField('name'); + testSchema.addNumber('quantity'); + testSchema.addBoolean('status'); + return testSchema.update(); + }) + .then(result => { + assert.equal(result.fields.status.type, 'Boolean'); + assert.equal(result.fields.quantity.type, 'Number'); + assert.equal(result.fields.name, undefined); + done(); + }); }); - it('multiple update', (done) => { + it('multiple update', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then(() => { - testSchema.addString('name'); - return testSchema.update(); - }).then(() => { - return testSchema.update(); - }).then(() => { - return testSchema.get(); - }).then((result) => { - assert.equal(Object.keys(result.fields).length, 5); - done(); - }); + testSchema + .save() + .then(() => { + testSchema.addString('name'); + return testSchema.update(); + }) + .then(() => { + return testSchema.update(); + }) + .then(() => { + return testSchema.get(); + }) + .then(result => { + assert.equal(Object.keys(result.fields).length, 5); + done(); + }); }); - it('delete', (done) => { + it('delete', done => { const testSchema1 = new Parse.Schema('SchemaTest1'); const testSchema2 = new Parse.Schema('SchemaTest2'); - testSchema1.save().then(() => { - return testSchema2.save(); - }).then(() => { - return Parse.Schema.all(); - }).then((results) => { - assert.equal(results.length, 2); - return testSchema1.delete(); - }).then(() => { - return Parse.Schema.all(); - }).then((results) => { - assert.equal(results.length, 1); - assert.equal(results[0].className, 'SchemaTest2'); - done(); - }); + testSchema1 + .save() + .then(() => { + return testSchema2.save(); + }) + .then(() => { + return Parse.Schema.all(); + }) + .then(results => { + assert.equal(results.length, 2); + return testSchema1.delete(); + }) + .then(() => { + return Parse.Schema.all(); + }) + .then(results => { + assert.equal(results.length, 1); + assert.equal(results[0].className, 'SchemaTest2'); + done(); + }); }); - it('purge', (done) => { + it('purge', done => { const testSchema = new Parse.Schema('SchemaTest'); const obj = new Parse.Object('SchemaTest'); - obj.save().then(() => { - return testSchema.delete().then(() => { - // Should never reach here - assert.equal(true, false); - }).catch((error) => { - assert.equal(error.code, Parse.Error.INVALID_SCHEMA_OPERATION); - assert.equal(error.message, 'Class SchemaTest is not empty, contains 1 objects, cannot drop schema.'); - return Promise.resolve(); + obj + .save() + .then(() => { + return testSchema + .delete() + .then(() => { + // Should never reach here + assert.equal(true, false); + }) + .catch(error => { + assert.equal(error.code, Parse.Error.INVALID_SCHEMA_OPERATION); + assert.equal( + error.message, + 'Class SchemaTest is not empty, contains 1 objects, cannot drop schema.' + ); + return Promise.resolve(); + }); + }) + .then(() => { + return testSchema.purge(); + }) + .then(() => { + const query = new Parse.Query('SchemaTest'); + return query.count(); + }) + .then(count => { + assert.equal(count, 0); + // Delete only works on empty schema, extra check + return testSchema.delete(); + }) + .then(() => { + done(); }); - }).then(() => { - return testSchema.purge(); - }).then(() => { - const query = new Parse.Query('SchemaTest'); - return query.count(); - }).then((count) => { - assert.equal(count, 0); - // Delete only works on empty schema, extra check - return testSchema.delete(); - }).then(() => { - done(); - }); }); - it('save index', (done) => { + it('save index', done => { const testSchema = new Parse.Schema('SchemaTest'); const index = { - name: 1 + name: 1, }; testSchema.addString('name'); testSchema.addIndex('test_index', index); - testSchema.save().then((result) => { + testSchema.save().then(result => { assert.notEqual(result.indexes.test_index, undefined); done(); }); }); - it('update index', (done) => { + it('update index', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then(() => { - const index = { - name: 1 - }; - testSchema.addString('name'); - testSchema.addIndex('test_index', index); - return testSchema.update(); - }).then((result) => { - assert.notEqual(result.indexes.test_index, undefined); - done(); - }); + testSchema + .save() + .then(() => { + const index = { + name: 1, + }; + testSchema.addString('name'); + testSchema.addIndex('test_index', index); + return testSchema.update(); + }) + .then(result => { + assert.notEqual(result.indexes.test_index, undefined); + done(); + }); }); - it('delete index', (done) => { + it('delete index', done => { const testSchema = new Parse.Schema('SchemaTest'); - testSchema.save().then(() => { - const index = { - name: 1 - }; - testSchema.addString('name'); - testSchema.addIndex('test_index', index); - return testSchema.update(); - }).then((result) => { - assert.notEqual(result.indexes.test_index, undefined); - testSchema.deleteIndex('test_index'); - return testSchema.update(); - }).then((result) => { - assert.equal(result.indexes.test_index, undefined); - done(); - }); + testSchema + .save() + .then(() => { + const index = { + name: 1, + }; + testSchema.addString('name'); + testSchema.addIndex('test_index', index); + return testSchema.update(); + }) + .then(result => { + assert.notEqual(result.indexes.test_index, undefined); + testSchema.deleteIndex('test_index'); + return testSchema.update(); + }) + .then(result => { + assert.equal(result.indexes.test_index, undefined); + done(); + }); }); - it('invalid field name', (done) => { + it('invalid field name', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addField(null); @@ -395,7 +497,7 @@ describe('Schema', () => { } }); - it('invalid field type', (done) => { + it('invalid field type', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addField('name', 'UnknownType'); @@ -404,7 +506,7 @@ describe('Schema', () => { } }); - it('invalid index name', (done) => { + it('invalid index name', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addIndex(null); @@ -413,7 +515,7 @@ describe('Schema', () => { } }); - it('invalid index', (done) => { + it('invalid index', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addIndex('name', null); @@ -422,7 +524,7 @@ describe('Schema', () => { } }); - it('invalid pointer name', (done) => { + it('invalid pointer name', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addPointer(null); @@ -431,7 +533,7 @@ describe('Schema', () => { } }); - it('invalid pointer class', (done) => { + it('invalid pointer class', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addPointer('name', null); @@ -440,7 +542,7 @@ describe('Schema', () => { } }); - it('invalid relation name', (done) => { + it('invalid relation name', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addRelation(null); @@ -449,7 +551,7 @@ describe('Schema', () => { } }); - it('invalid relation class', (done) => { + it('invalid relation class', done => { const testSchema = new Parse.Schema('SchemaTest'); try { testSchema.addRelation('name', null); @@ -458,7 +560,7 @@ describe('Schema', () => { } }); - it('assert class name', (done) => { + it('assert class name', done => { const testSchema = new Parse.Schema(); try { testSchema.assertClassName(); diff --git a/integration/test/ParseSubclassTest.js b/integration/test/ParseSubclassTest.js index a1cab7a94..ef7a17bc4 100644 --- a/integration/test/ParseSubclassTest.js +++ b/integration/test/ParseSubclassTest.js @@ -5,177 +5,197 @@ const clear = require('./clear'); const Parse = require('../../node'); describe('Parse Object Subclasses', () => { - beforeEach((done) => { + beforeEach(done => { Parse.initialize('integration', null, 'notsosecret'); Parse.CoreManager.set('SERVER_URL', 'http://localhost:1337/parse'); Parse.Storage._clear(); clear().then(done); }); - it('uses subclasses when doing query find', (done) => { + it('uses subclasses when doing query find', done => { const Subclass = Parse.Object.extend('Subclass', { initialize(attributes, options, number) { this.number = number || -1; - } + }, }); const object = new Subclass({}, {}, 57); assert.equal(object.number, 57); - object.save().then(() => { - const query = new Parse.Query(Subclass); - return query.find(); - }).then((results) => { - assert.equal(results.length, 1); - assert(results[0] instanceof Subclass); - assert.equal(results[0].number, -1); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(Subclass); + return query.find(); + }) + .then(results => { + assert.equal(results.length, 1); + assert(results[0] instanceof Subclass); + assert.equal(results[0].number, -1); + done(); + }); }); - it('uses subclasses when doing query get', (done) => { + it('uses subclasses when doing query get', done => { const Subclass = Parse.Object.extend('Subclass', { initialize(attributes, options, number) { this.number = number || -1; - } + }, }); const object = new Subclass({}, {}, 57); assert.equal(object.number, 57); - object.save().then(() => { - const query = new Parse.Query(Subclass); - return query.get(object.id); - }).then((result) => { - assert(result instanceof Subclass); - assert.equal(result.number, -1); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(Subclass); + return query.get(object.id); + }) + .then(result => { + assert(result instanceof Subclass); + assert.equal(result.number, -1); + done(); + }); }); - it('uses subclasses with array results', (done) => { + it('uses subclasses with array results', done => { const Container = Parse.Object.extend('Container'); const Item = Parse.Object.extend('Item'); const ItemChild = Parse.Object.extend('Item'); const ItemGrandchild = ItemChild.extend(); const item = new Item(); - item.save({ foo: 'bar' }).then(() => { - const container = new Container(); - return container.save({ items: [item] }); - }).then((container) => { - const query = new Parse.Query(Container); - return query.get(container.id); - }).then((container) => { - assert(container instanceof Container); - assert.equal(container.get('items').length, 1); - const item = container.get('items')[0]; - assert(item instanceof Item); - assert(item instanceof ItemChild); - assert(item instanceof ItemGrandchild); - done(); - }); + item + .save({ foo: 'bar' }) + .then(() => { + const container = new Container(); + return container.save({ items: [item] }); + }) + .then(container => { + const query = new Parse.Query(Container); + return query.get(container.id); + }) + .then(container => { + assert(container instanceof Container); + assert.equal(container.get('items').length, 1); + const item = container.get('items')[0]; + assert(item instanceof Item); + assert(item instanceof ItemChild); + assert(item instanceof ItemGrandchild); + done(); + }); }); - it('can subclass multiple levels explicitly', (done) => { + it('can subclass multiple levels explicitly', done => { const Parent = Parse.Object.extend('MyClass', { initialize() { Parent.__super__.initialize.apply(this, arguments); this.parent = true; - } + }, }); const Child = Parent.extend({ initialize() { Child.__super__.initialize.apply(this, arguments); this.child = true; - } + }, }); const Grandchild = Child.extend({ initialize() { Grandchild.__super__.initialize.apply(this, arguments); this.grandchild = true; - } + }, }); const object = new Parent(); - object.save().then(() => { - const query = new Parse.Query(Grandchild); - return query.get(object.id); - }).then((result) => { - assert(result instanceof Parent); - assert(result instanceof Child); - assert(result instanceof Grandchild); - assert(result.parent); - assert(result.child); - assert(result.grandchild); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(Grandchild); + return query.get(object.id); + }) + .then(result => { + assert(result instanceof Parent); + assert(result instanceof Child); + assert(result instanceof Grandchild); + assert(result.parent); + assert(result.child); + assert(result.grandchild); + done(); + }); }); - it('can subclass multiple levels implicitly', (done) => { + it('can subclass multiple levels implicitly', done => { const Parent = Parse.Object.extend('MyClass', { initialize() { Parent.__super__.initialize.apply(this, arguments); this.parent = true; - } + }, }); const Child = Parse.Object.extend('MyClass', { initialize() { Child.__super__.initialize.apply(this, arguments); this.child = true; - } + }, }); const Grandchild = Parse.Object.extend('MyClass', { initialize() { Grandchild.__super__.initialize.apply(this, arguments); this.grandchild = true; - } + }, }); const object = new Parent(); - object.save().then(() => { - const query = new Parse.Query(Grandchild); - return query.get(object.id); - }).then((result) => { - assert(result instanceof Parent); - assert(result instanceof Child); - assert(result instanceof Grandchild); - assert(result.parent); - assert(result.child); - assert(result.grandchild); - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(Grandchild); + return query.get(object.id); + }) + .then(result => { + assert(result instanceof Parent); + assert(result instanceof Child); + assert(result instanceof Grandchild); + assert(result.parent); + assert(result.child); + assert(result.grandchild); + done(); + }); }); - it('can subclass multiple levels explicitly with different names', (done) => { + it('can subclass multiple levels explicitly with different names', done => { const Parent = Parse.Object.extend('MyClass'); const Child = Parent.extend(); const Grandchild = Child.extend('NewClass'); const object = new Parent(); - object.save().then(() => { - const query = new Parse.Query(Child); - return query.get(object.id); - }).then((result) => { - assert(result instanceof Parent); - assert(result instanceof Child); - - const query = new Parse.Query(Grandchild); - return query.get(object.id); - }).then(null, () => { - // No object found - done(); - }); + object + .save() + .then(() => { + const query = new Parse.Query(Child); + return query.get(object.id); + }) + .then(result => { + assert(result instanceof Parent); + assert(result instanceof Child); + + const query = new Parse.Query(Grandchild); + return query.get(object.id); + }) + .then(null, () => { + // No object found + done(); + }); }); it('propagates instance properties', () => { const Squirtle = Parse.Object.extend('Squirtle', { - water: true + water: true, }); const Wartortle = Squirtle.extend('Wartortle'); const wartortle = new Wartortle(); diff --git a/integration/test/ParseUserTest.js b/integration/test/ParseUserTest.js index e9d338bb9..21dba77c1 100644 --- a/integration/test/ParseUserTest.js +++ b/integration/test/ParseUserTest.js @@ -38,7 +38,7 @@ const authResponse = { }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, getAuthResponse: () => authResponse, @@ -52,71 +52,83 @@ describe('Parse User', () => { Parse.Object.registerSubclass('_User', Parse.User); }); - beforeEach((done) => { + beforeEach(done => { let promise = Promise.resolve(); try { promise = Parse.User.logOut(); - } catch (e) { /**/ } // eslint-disable-line no-unused-vars - promise.then(() => { - return clear(); - }).then(() => { - done(); - }); + } catch (e) { + /**/ + } // eslint-disable-line no-unused-vars + promise + .then(() => { + return clear(); + }) + .then(() => { + done(); + }); }); - it('can sign up users via static method', (done) => { - Parse.User.signUp('asdf', 'zxcv').then((user) => { + it('can sign up users via static method', done => { + Parse.User.signUp('asdf', 'zxcv').then(user => { assert(user.getSessionToken()); expect(user.existed()).toBe(false); done(); }); }); - it('can sign up via instance method', (done) => { + it('can sign up via instance method', done => { const user = new Parse.User(); user.setPassword('asdf'); user.setUsername('zxcv'); - user.signUp().then((user) => { + user.signUp().then(user => { assert(user.getSessionToken()); expect(user.existed()).toBe(false); done(); }); }); - it('fails log in with wrong username', (done) => { - Parse.User.signUp('asdf', 'zxcv').then(() => { - return Parse.User.logIn('false_user', 'asdf3'); - }).then(null, () => { - done(); - }); + it('fails log in with wrong username', done => { + Parse.User.signUp('asdf', 'zxcv') + .then(() => { + return Parse.User.logIn('false_user', 'asdf3'); + }) + .then(null, () => { + done(); + }); }); - it('fails log in with wrong password', (done) => { - Parse.User.signUp('asdf', 'zxcv').then(() => { - return Parse.User.logIn('asdf', 'asdfWrong'); - }).then(null, () => { - done(); - }); + it('fails log in with wrong password', done => { + Parse.User.signUp('asdf', 'zxcv') + .then(() => { + return Parse.User.logIn('asdf', 'asdfWrong'); + }) + .then(null, () => { + done(); + }); }); - it('can log in a user', (done) => { - Parse.User.signUp('asdf', 'zxcv').then(() => { - return Parse.User.logIn('asdf', 'zxcv'); - }).then((user) => { - assert.equal(user.get('username'), 'asdf'); - expect(user.existed()).toBe(true); - done(); - }); + it('can log in a user', done => { + Parse.User.signUp('asdf', 'zxcv') + .then(() => { + return Parse.User.logIn('asdf', 'zxcv'); + }) + .then(user => { + assert.equal(user.get('username'), 'asdf'); + expect(user.existed()).toBe(true); + done(); + }); }); - it('can log in a user using POST method', (done) => { - Parse.User.signUp('asdf', 'zxcv').then(() => { - return Parse.User.logIn('asdf', 'zxcv', { usePost: true }); - }).then((user) => { - assert.equal(user.get('username'), 'asdf'); - expect(user.existed()).toBe(true); - done(); - }); + it('can log in a user using POST method', done => { + Parse.User.signUp('asdf', 'zxcv') + .then(() => { + return Parse.User.logIn('asdf', 'zxcv', { usePost: true }); + }) + .then(user => { + assert.equal(user.get('username'), 'asdf'); + expect(user.existed()).toBe(true); + done(); + }); }); it('can login users with installationId', async () => { @@ -145,7 +157,9 @@ describe('Parse User', () => { expect(sessions[1].get('sessionToken')).toBe(loggedUser.getSessionToken()); // Should clean up sessions - const installationUser = await Parse.User.logIn('parse', 'mypass', { installationId }); + const installationUser = await Parse.User.logIn('parse', 'mypass', { + installationId, + }); sessions = await sessionQuery.find({ useMasterKey: true }); expect(sessions.length).toBe(2); expect(sessions[0].get('installationId')).toBe(currentInstallation); @@ -154,38 +168,43 @@ describe('Parse User', () => { expect(sessions[1].get('sessionToken')).toBe(installationUser.getSessionToken()); }); - it('can become a user', (done) => { + it('can become a user', done => { Parse.User.enableUnsafeCurrentUser(); let session = null; let newUser = null; - Parse.User.signUp('jason', 'parse', {'code': 'red'}).then((user) => { - newUser = user; - assert.equal(Parse.User.current(), newUser); - session = newUser.getSessionToken(); - assert(session); - - return Parse.User.logOut(); - }).then(() => { - assert(!Parse.User.current()); - - return Parse.User.become(session); - }).then((user) => { - assert.equal(Parse.User.current(), user); - assert(user); - assert.equal(user.id, newUser.id) - assert.equal(user.get('code'), 'red'); - - return Parse.User.logOut(); - }).then(() => { - assert(!Parse.User.current()); - - return Parse.User.become('garbage'); - }).then(null, () => { - done(); - }); + Parse.User.signUp('jason', 'parse', { code: 'red' }) + .then(user => { + newUser = user; + assert.equal(Parse.User.current(), newUser); + session = newUser.getSessionToken(); + assert(session); + + return Parse.User.logOut(); + }) + .then(() => { + assert(!Parse.User.current()); + + return Parse.User.become(session); + }) + .then(user => { + assert.equal(Parse.User.current(), user); + assert(user); + assert.equal(user.id, newUser.id); + assert.equal(user.get('code'), 'red'); + + return Parse.User.logOut(); + }) + .then(() => { + assert(!Parse.User.current()); + + return Parse.User.become('garbage'); + }) + .then(null, () => { + done(); + }); }); - it('cannot save non-authed user', (done) => { + it('cannot save non-authed user', done => { let user = new Parse.User(); let notAuthed = null; user.set({ @@ -193,91 +212,109 @@ describe('Parse User', () => { email: 'asdf@example.com', username: 'zxcv', }); - user.signUp().then((userAgain) => { - assert.equal(user, userAgain); - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((userNotAuthed) => { - notAuthed = userNotAuthed; - user = new Parse.User(); - user.set({ - username: 'hacker', - password: 'password', + user + .signUp() + .then(userAgain => { + assert.equal(user, userAgain); + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(userNotAuthed => { + notAuthed = userNotAuthed; + user = new Parse.User(); + user.set({ + username: 'hacker', + password: 'password', + }); + return user.signUp(); + }) + .then(userAgain => { + assert.equal(userAgain, user); + notAuthed.set('username', 'changed'); + return notAuthed.save(); + }) + .then(null, e => { + assert.equal(e.code, Parse.Error.SESSION_MISSING); + done(); }); - return user.signUp(); - }).then((userAgain) => { - assert.equal(userAgain, user); - notAuthed.set('username', 'changed'); - return notAuthed.save(); - }).then(null, (e) => { - assert.equal(e.code, Parse.Error.SESSION_MISSING); - done(); - }); }); - it('cannot delete non-authed user', (done) => { + it('cannot delete non-authed user', done => { let user = new Parse.User(); let notAuthed = null; - user.signUp({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', - }).then(() => { - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((userNotAuthed) => { - notAuthed = userNotAuthed; - user = new Parse.User(); - return user.signUp({ - username: 'hacker', - password: 'password', + user + .signUp({ + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', + }) + .then(() => { + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(userNotAuthed => { + notAuthed = userNotAuthed; + user = new Parse.User(); + return user.signUp({ + username: 'hacker', + password: 'password', + }); + }) + .then(userAgain => { + assert.equal(userAgain, user); + notAuthed.set('username', 'changed'); + return notAuthed.destroy(); + }) + .then(null, e => { + assert.equal(e.code, Parse.Error.SESSION_MISSING); + done(); }); - }).then((userAgain) => { - assert.equal(userAgain, user); - notAuthed.set('username', 'changed'); - return notAuthed.destroy(); - }).then(null, (e) => { - assert.equal(e.code, Parse.Error.SESSION_MISSING); - done(); - }); }); - it('cannot saveAll with non-authed user', (done) => { + it('cannot saveAll with non-authed user', done => { let user = new Parse.User(); let notAuthed = null; - user.signUp({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', - }).then(() => { - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((userNotAuthed) => { - notAuthed = userNotAuthed; - user = new Parse.User(); - return user.signUp({ - username: 'hacker', - password: 'password', + user + .signUp({ + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', + }) + .then(() => { + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(userNotAuthed => { + notAuthed = userNotAuthed; + user = new Parse.User(); + return user.signUp({ + username: 'hacker', + password: 'password', + }); + }) + .then(() => { + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(userNotAuthedNotChanged => { + notAuthed.set('username', 'changed'); + const object = new TestObject(); + return object.save({ user: userNotAuthedNotChanged }); + }) + .then(() => { + const item1 = new TestObject(); + return item1.save({ number: 0 }); + }) + .then(item1 => { + item1.set('number', 1); + const item2 = new TestObject(); + item2.set('number', 2); + return Parse.Object.saveAll([item1, item2, notAuthed]); + }) + .then(null, e => { + assert.equal(e.code, Parse.Error.SESSION_MISSING); + done(); }); - }).then(() => { - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((userNotAuthedNotChanged) => { - notAuthed.set('username', 'changed'); - const object = new TestObject(); - return object.save({ user: userNotAuthedNotChanged }); - }).then(() => { - const item1 = new TestObject(); - return item1.save({ number: 0 }); - }).then((item1) => { - item1.set('number', 1); - const item2 = new TestObject(); - item2.set('number', 2); - return Parse.Object.saveAll([item1, item2, notAuthed]); - }).then(null, (e) => { - assert.equal(e.code, Parse.Error.SESSION_MISSING); - done(); - }); }); it('can fetch non-auth user with include', async () => { @@ -329,28 +366,31 @@ describe('Parse User', () => { assert.equal(Parse.User.current().get('child').get('field'), 'test'); }); - it('can store the current user', (done) => { + it('can store the current user', done => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); user.set('password', 'asdf'); user.set('email', 'asdf@example.com'); user.set('username', 'zxcv'); - user.signUp().then(() => { - const current = Parse.User.current(); - assert.equal(user.id, current.id); - assert(user.getSessionToken()); - - const currentAgain = Parse.User.current(); - assert.equal(current, currentAgain); - - return Parse.User.logOut(); - }).then(() => { - assert.equal(Parse.User.current(), null); - done(); - }); + user + .signUp() + .then(() => { + const current = Parse.User.current(); + assert.equal(user.id, current.id); + assert(user.getSessionToken()); + + const currentAgain = Parse.User.current(); + assert.equal(current, currentAgain); + + return Parse.User.logOut(); + }) + .then(() => { + assert.equal(Parse.User.current(), null); + done(); + }); }); - it('can test if a user is current', (done) => { + it('can test if a user is current', done => { Parse.User.enableUnsafeCurrentUser(); const user1 = new Parse.User(); const user2 = new Parse.User(); @@ -364,145 +404,171 @@ describe('Parse User', () => { user2.set('password', 'password'); user3.set('password', 'password'); - user1.signUp().then(() => { - assert(user1.isCurrent()); - assert(!user2.isCurrent()); - assert(!user3.isCurrent()); - - return user2.signUp(); - }).then(() => { - assert(!user1.isCurrent()); - assert(user2.isCurrent()); - assert(!user3.isCurrent()); - - return user3.signUp(); - }).then(() => { - assert(!user1.isCurrent()); - assert(!user2.isCurrent()); - assert(user3.isCurrent()); - - return Parse.User.logIn('a', 'password'); - }).then(() => { - assert(user1.isCurrent()); - assert(!user2.isCurrent()); - assert(!user3.isCurrent()); - - return Parse.User.logIn('b', 'password'); - }).then(() => { - assert(!user1.isCurrent()); - assert(user2.isCurrent()); - assert(!user3.isCurrent()); - - return Parse.User.logIn('c', 'password'); - }).then(() => { - assert(!user1.isCurrent()); - assert(!user2.isCurrent()); - assert(user3.isCurrent()); - - return Parse.User.logOut(); - }).then(() => { - assert(!user3.isCurrent()); - done(); - }); + user1 + .signUp() + .then(() => { + assert(user1.isCurrent()); + assert(!user2.isCurrent()); + assert(!user3.isCurrent()); + + return user2.signUp(); + }) + .then(() => { + assert(!user1.isCurrent()); + assert(user2.isCurrent()); + assert(!user3.isCurrent()); + + return user3.signUp(); + }) + .then(() => { + assert(!user1.isCurrent()); + assert(!user2.isCurrent()); + assert(user3.isCurrent()); + + return Parse.User.logIn('a', 'password'); + }) + .then(() => { + assert(user1.isCurrent()); + assert(!user2.isCurrent()); + assert(!user3.isCurrent()); + + return Parse.User.logIn('b', 'password'); + }) + .then(() => { + assert(!user1.isCurrent()); + assert(user2.isCurrent()); + assert(!user3.isCurrent()); + + return Parse.User.logIn('c', 'password'); + }) + .then(() => { + assert(!user1.isCurrent()); + assert(!user2.isCurrent()); + assert(user3.isCurrent()); + + return Parse.User.logOut(); + }) + .then(() => { + assert(!user3.isCurrent()); + done(); + }); }); - it('can query for users', (done) => { + it('can query for users', done => { const user = new Parse.User(); user.set('password', 'asdf'); user.set('email', 'asdf@exxample.com'); user.set('username', 'zxcv'); - user.signUp().then(() => { - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((u) => { - assert.equal(u.id, user.id); - return new Parse.Query(Parse.User).find(); - }).then((users) => { - assert.equal(users.length, 1); - assert.equal(users[0].id, user.id); - done(); - }); + user + .signUp() + .then(() => { + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(u => { + assert.equal(u.id, user.id); + return new Parse.Query(Parse.User).find(); + }) + .then(users => { + assert.equal(users.length, 1); + assert.equal(users[0].id, user.id); + done(); + }); }); - it('preserves the session token when querying the current user', (done) => { + it('preserves the session token when querying the current user', done => { const user = new Parse.User(); user.set('password', 'asdf'); user.set('email', 'asdf@example.com'); user.set('username', 'zxcv'); - user.signUp().then(() => { - assert(user.has('sessionToken')); - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then((u) => { - // Old object maintains token - assert(user.has('sessionToken')); - // New object doesn't have token - assert(!u.has('sessionToken')); - done(); - }); + user + .signUp() + .then(() => { + assert(user.has('sessionToken')); + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(u => { + // Old object maintains token + assert(user.has('sessionToken')); + // New object doesn't have token + assert(!u.has('sessionToken')); + done(); + }); }); - it('does not log in a user when saving', (done) => { + it('does not log in a user when saving', done => { Parse.User.enableUnsafeCurrentUser(); const user = new Parse.User(); - user.save({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', - }).then(() => { - assert(!Parse.User.current()); - done(); - }); + user + .save({ + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', + }) + .then(() => { + assert(!Parse.User.current()); + done(); + }); }); - it('can update users', (done) => { + it('can update users', done => { const user = new Parse.User(); - user.signUp({ - password: 'asdf', - email: 'asdf@example.com', - username: 'zxcv', - }).then(() => { - user.set('username', 'test'); - return user.save(); - }).then(() => { - assert.equal(Object.keys(user.attributes).length, 6); - assert(user.attributes.hasOwnProperty('username')); - assert(user.attributes.hasOwnProperty('email')); - return user.destroy(); - }).then(() => { - const query = new Parse.Query(Parse.User); - return query.get(user.id); - }).then(null, (e) => { - assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); - done(); - }); + user + .signUp({ + password: 'asdf', + email: 'asdf@example.com', + username: 'zxcv', + }) + .then(() => { + user.set('username', 'test'); + return user.save(); + }) + .then(() => { + assert.equal(Object.keys(user.attributes).length, 6); + assert(user.attributes.hasOwnProperty('username')); + assert(user.attributes.hasOwnProperty('email')); + return user.destroy(); + }) + .then(() => { + const query = new Parse.Query(Parse.User); + return query.get(user.id); + }) + .then(null, e => { + assert.equal(e.code, Parse.Error.OBJECT_NOT_FOUND); + done(); + }); }); - it('can count users', (done) => { + it('can count users', done => { const james = new Parse.User(); james.set('username', 'james'); james.set('password', 'mypass'); - james.signUp().then(() => { - const kevin = new Parse.User(); - kevin.set('username', 'kevin'); - kevin.set('password', 'mypass'); - return kevin.signUp(); - }).then(() => { - const query = new Parse.Query(Parse.User); - return query.count(); - }).then((c) => { - assert.equal(c, 2); - done(); - }); + james + .signUp() + .then(() => { + const kevin = new Parse.User(); + kevin.set('username', 'kevin'); + kevin.set('password', 'mypass'); + return kevin.signUp(); + }) + .then(() => { + const query = new Parse.Query(Parse.User); + return query.count(); + }) + .then(c => { + assert.equal(c, 2); + done(); + }); }); - it('can sign up user with container class', (done) => { - Parse.User.signUp('ilya', 'mypass', { 'array': ['hello'] }).then(() => { + it('can sign up user with container class', done => { + Parse.User.signUp('ilya', 'mypass', { array: ['hello'] }).then(() => { done(); }); }); - it('handles user subclassing', (done) => { + it('handles user subclassing', done => { const SuperUser = Parse.Object.extend('User'); const user = new SuperUser(); user.set('username', 'bob'); @@ -513,14 +579,14 @@ describe('Parse User', () => { }); }); - it('uses subclasses when doing signup', (done) => { + it('uses subclasses when doing signup', done => { const SuperUser = Parse.User.extend({ secret() { return 1337; - } + }, }); - Parse.User.signUp('bob', 'welcome').then((user) => { + Parse.User.signUp('bob', 'welcome').then(user => { assert(user instanceof SuperUser); assert.equal(user.secret(), 1337); done(); @@ -727,7 +793,7 @@ describe('Parse User', () => { let user = await CustomUser.signUp('username', 'password'); const token = user.getSessionToken(); - user = await CustomUser.become(token) + user = await CustomUser.become(token); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); @@ -738,7 +804,7 @@ describe('Parse User', () => { let user = await CustomUser.signUp('username', 'password'); const token = user.getSessionToken(); - user = await CustomUser.me(token) + user = await CustomUser.me(token); expect(user instanceof CustomUser).toBe(true); expect(user.doSomething()).toBe(5); }); @@ -789,7 +855,9 @@ describe('Parse User', () => { user.setUsername('Alice'); user.setPassword('sekrit'); await user.save(null, { useMasterKey: true }); - await user.linkWith(provider.getAuthType(), provider.getAuthData(), { useMasterKey: true }); + await user.linkWith(provider.getAuthType(), provider.getAuthData(), { + useMasterKey: true, + }); expect(user._isLinked(provider)).toBe(true); await user._unlinkFrom(provider, { useMasterKey: true }); expect(user._isLinked(provider)).toBe(false); @@ -805,7 +873,9 @@ describe('Parse User', () => { expect(user.isCurrent()).toBe(false); const sessionToken = user.getSessionToken(); - await user.linkWith(provider.getAuthType(), provider.getAuthData(), { sessionToken }); + await user.linkWith(provider.getAuthType(), provider.getAuthData(), { + sessionToken, + }); expect(user._isLinked(provider)).toBe(true); await user._unlinkFrom(provider, { sessionToken }); expect(user._isLinked(provider)).toBe(false); @@ -816,7 +886,9 @@ describe('Parse User', () => { user.setUsername('Alice'); user.setPassword('sekrit'); await user.save(null, { useMasterKey: true }); - await user.linkWith(provider.getAuthType(), provider.getAuthData(), { useMasterKey: true }); + await user.linkWith(provider.getAuthType(), provider.getAuthData(), { + useMasterKey: true, + }); expect(user._isLinked(provider)).toBe(true); expect(user.authenticated()).toBeFalsy(); Parse.User.enableUnsafeCurrentUser(); @@ -902,10 +974,10 @@ describe('Parse User', () => { Parse.User.enableUnsafeCurrentUser(); const authData = { id: 227463280, - consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", - consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", - auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + consumer_key: '5QiVwxr8FQHbo5CMw46Z0jquF', + consumer_secret: 'p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK', + auth_token: '227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc', + auth_token_secret: 'G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr', }; const user = new Parse.User(); user.setUsername('Alice'); @@ -926,10 +998,10 @@ describe('Parse User', () => { Parse.FacebookUtils.init(); const authData = { id: 227463280, - consumer_key: "5QiVwxr8FQHbo5CMw46Z0jquF", - consumer_secret: "p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK", - auth_token: "227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc", - auth_token_secret: "G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr" + consumer_key: '5QiVwxr8FQHbo5CMw46Z0jquF', + consumer_secret: 'p05FDlIRAnOtqJtjIt0xcw390jCcjj56QMdE9B52iVgOEb7LuK', + auth_token: '227463280-lngpMGXdnG36JiuzGfAYbKcZUPwjmcIV2NqL9hWc', + auth_token_secret: 'G1tl1R0gaYKTyxw0uYJDKRoVhM16ifyLeMwIaKlFtPkQr', }; const user = new Parse.User(); user.setUsername('Alice'); diff --git a/integration/test/clear.js b/integration/test/clear.js index ed8ae85c2..2ae35ef2a 100644 --- a/integration/test/clear.js +++ b/integration/test/clear.js @@ -7,6 +7,6 @@ const Parse = require('../../node'); * @param {boolean} fast set to true if it's ok to just drop objects and not indexes. * @returns {Promise} A promise that is resolved when database is deleted. */ -module.exports = function(fast = true) { +module.exports = function (fast = true) { return Parse._ajax('GET', `http://localhost:1337/clear/${fast}`, ''); }; diff --git a/integration/test/helper.js b/integration/test/helper.js index eea52a040..bade717bf 100644 --- a/integration/test/helper.js +++ b/integration/test/helper.js @@ -1,7 +1,7 @@ const ParseServer = require('parse-server').ParseServer; jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; -beforeAll((done) => { +beforeAll(done => { const { app } = require('../server'); const httpServer = require('http').createServer(app); diff --git a/integration/test/mockLocalStorage.js b/integration/test/mockLocalStorage.js index eadaf9731..0728bfb8e 100644 --- a/integration/test/mockLocalStorage.js +++ b/integration/test/mockLocalStorage.js @@ -9,7 +9,6 @@ let mockStorage = {}; const mockLocalStorage = { - getItem(path) { return mockStorage[path] || null; }, @@ -26,7 +25,7 @@ const mockLocalStorage = { return Object.keys(mockStorage).length; }, - key: (i) => { + key: i => { const keys = Object.keys(mockStorage); return keys[i] || null; }, diff --git a/integration/test/mockRNStorage.js b/integration/test/mockRNStorage.js index 9318d2451..006585211 100644 --- a/integration/test/mockRNStorage.js +++ b/integration/test/mockRNStorage.js @@ -28,12 +28,12 @@ const mockRNStorage = { }, multiGet(keys, cb) { - const objects = keys.map((key) => [key, mockStorage[key]]); + const objects = keys.map(key => [key, mockStorage[key]]); cb(undefined, objects); }, multiRemove(keys, cb) { - keys.map((key) => delete mockStorage[key]); + keys.map(key => delete mockStorage[key]); cb(undefined); }, diff --git a/integration/test/sleep.js b/integration/test/sleep.js index c334fd7cb..d45cb89c9 100644 --- a/integration/test/sleep.js +++ b/integration/test/sleep.js @@ -1,5 +1,5 @@ -module.exports = function(ms) { - return new Promise(function(resolve) { +module.exports = function (ms) { + return new Promise(function (resolve) { setTimeout(resolve, ms); }); }; diff --git a/package-lock.json b/package-lock.json index 0c47ceb52..b8f63029e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1304,47 +1304,6 @@ "kuler": "^2.0.0" } }, - "@graphql-tools/batch-delegate": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-delegate/-/batch-delegate-6.2.2.tgz", - "integrity": "sha512-xXJKVvBxafdn9tVWe3oJreTHuFAKWblw4zK0KvKhEVJOjPytKweGCZI3kTs9hdmjgPz1ZjSQEVvgmZJ0GubrWA==", - "dev": true, - "requires": { - "@graphql-tools/delegate": "6.2.2", - "dataloader": "2.0.0", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, - "@graphql-tools/delegate": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-6.2.2.tgz", - "integrity": "sha512-8VycfZYQ+m4HgajewQT6v6BzAEFxc6mh6rO+uqewnvh143nvv3ud4nXEAfOddUm0PrE6iD3Ng2BZtPSWF5mt+w==", - "dev": true, - "requires": { - "@ardatan/aggregate-error": "0.0.6", - "@graphql-tools/schema": "6.2.2", - "@graphql-tools/utils": "6.2.2", - "dataloader": "2.0.0", - "is-promise": "4.0.0", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, "@graphql-tools/links": { "version": "6.2.5", "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-6.2.5.tgz", @@ -1390,125 +1349,6 @@ } } }, - "@graphql-tools/merge": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.2.tgz", - "integrity": "sha512-2YyErSvq4hn5mjE6qJ/0Q8r3WU9JB3+obv2xyvb+oW+E/T1iYRJGxSFldi6lqO5IADZz8QASLJeSpRBw40gpBg==", - "dev": true, - "requires": { - "@graphql-tools/schema": "6.2.2", - "@graphql-tools/utils": "6.2.2", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, - "@graphql-tools/schema": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.2.tgz", - "integrity": "sha512-KITlyr//1oKyxIOlGvNZDl4c6bLj2Gc+3eJXyUKWfSmgsmAZPudpQNa/8VbiVujpm7UaX0cyM3FdeCaxWFeBgg==", - "dev": true, - "requires": { - "@graphql-tools/utils": "6.2.2", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, - "@graphql-tools/stitch": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/stitch/-/stitch-6.2.2.tgz", - "integrity": "sha512-VysuOBik1ICqsgV3VGXysJfdUl4/ro95rsnREma9BJP3oNqriPd6v8JhrnZqP2LbfzF7G2xndRoSRAQgYOzsUQ==", - "dev": true, - "requires": { - "@graphql-tools/batch-delegate": "6.2.2", - "@graphql-tools/delegate": "6.2.2", - "@graphql-tools/merge": "6.2.2", - "@graphql-tools/schema": "6.2.2", - "@graphql-tools/utils": "6.2.2", - "@graphql-tools/wrap": "6.2.2", - "is-promise": "4.0.0", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, - "@graphql-tools/utils": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.2.tgz", - "integrity": "sha512-a0SSYF76dnKHs8te4Igfnrrq1VOO4sFG8yx3ehO7464eGUfUUYo2QmNRjhxny2HRMvqzX40xuQikyg6LBXDNLQ==", - "dev": true, - "requires": { - "@ardatan/aggregate-error": "0.0.6", - "camel-case": "4.1.1", - "tslib": "~2.0.1" - }, - "dependencies": { - "camel-case": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", - "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", - "dev": true, - "requires": { - "pascal-case": "^3.1.1", - "tslib": "^1.10.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, - "@graphql-tools/wrap": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-6.2.2.tgz", - "integrity": "sha512-FjCE+NvMwcCiAlt9EAw9uDi2zblE4Z5CEkY+z4NRO1AmCB5THoWJKG+csPh8tGuU80mAJI51Wy9FQGyUo/EU0g==", - "dev": true, - "requires": { - "@graphql-tools/delegate": "6.2.2", - "@graphql-tools/schema": "6.2.2", - "@graphql-tools/utils": "6.2.2", - "is-promise": "4.0.0", - "tslib": "~2.0.1" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "dev": true - } - } - }, "@graphql-typed-document-node/core": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.0.tgz", @@ -1744,119 +1584,12 @@ } } }, - "@parse/fs-files-adapter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.0.1.tgz", - "integrity": "sha1-do94QIPo+Wc+9GPhmaG+X4N7QWU=", - "dev": true - }, "@parse/minami": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@parse/minami/-/minami-1.0.0.tgz", "integrity": "sha512-Rw+p0WdOOypFPVJsmhyiI+Q056ZxdP2iAtObnU1DZrsvKZTf5x0B/0SjIt0hUgWp+COjqi/p17VdBU9IAD/NJg==", "dev": true }, - "@parse/node-apn": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-3.2.0.tgz", - "integrity": "sha512-Xa2paSzLY18k0ekvVAa9YbwwxGjzFnnAu7fqwlrFhaWCv1IaQ9u7r/TGuLml1zWbvhFTdy4XXB4soDS1pek3uA==", - "dev": true, - "requires": { - "debug": "3.1.0", - "jsonwebtoken": "8.1.0", - "node-forge": "0.10.0", - "verror": "1.10.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", - "dev": true, - "requires": { - "jws": "^3.1.4", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.0.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", - "dev": true - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", - "dev": true - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", - "dev": true - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "@parse/node-gcm": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz", @@ -1923,116 +1656,6 @@ } } }, - "@parse/push-adapter": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.3.0.tgz", - "integrity": "sha512-PQlgP5ydplSZlC2jCx79j/5A8FVD1i7yl3796RL/zC4dj9TZ4Hocc/IVjru4aFHB129zwXQeyJBmtByySP95uw==", - "dev": true, - "requires": { - "@parse/node-apn": "3.2.0", - "@parse/node-gcm": "1.0.2", - "npmlog": "4.0.2", - "parse": "2.16.0" - }, - "dependencies": { - "parse": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-2.16.0.tgz", - "integrity": "sha512-MJRGCYZGawOs9FOn/i/ag7IFF9NHe5OG+XvNta45pSMzre6nvqUqcvQpTDj0tC+h0C4eMuLoI39SQ07PIwnRTw==", - "dev": true, - "requires": { - "@babel/runtime": "7.11.2", - "@babel/runtime-corejs3": "7.11.2", - "crypto-js": "4.0.0", - "react-native-crypto-js": "1.0.0", - "uuid": "3.4.0", - "ws": "7.3.1", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true - } - } - } - } - }, - "@parse/s3-files-adapter": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.5.0.tgz", - "integrity": "sha512-dF4IkGgP2o1iiuTsrHz2Y4hASE/QMMXIcOLf0hxA1e1fBYQ1oLphquoaFldO0Li0wUIE0zg5vuIAkp1M4ODqjQ==", - "dev": true, - "requires": { - "aws-sdk": "2.761.0", - "parse": "2.16.0" - }, - "dependencies": { - "parse": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-2.16.0.tgz", - "integrity": "sha512-MJRGCYZGawOs9FOn/i/ag7IFF9NHe5OG+XvNta45pSMzre6nvqUqcvQpTDj0tC+h0C4eMuLoI39SQ07PIwnRTw==", - "dev": true, - "requires": { - "@babel/runtime": "7.11.2", - "@babel/runtime-corejs3": "7.11.2", - "crypto-js": "4.0.0", - "react-native-crypto-js": "1.0.0", - "uuid": "3.4.0", - "ws": "7.3.1", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", - "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, - "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true - } - } - } - } - }, "@parse/simple-mailgun-adapter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@parse/simple-mailgun-adapter/-/simple-mailgun-adapter-1.1.0.tgz", @@ -2380,6 +2003,12 @@ } } }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, "@types/qs": { "version": "6.9.5", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", @@ -2562,6 +2191,16 @@ "debug": "4" } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.5", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", @@ -2640,16 +2279,6 @@ "normalize-path": "^2.1.1" } }, - "apollo-cache-control": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.3.tgz", - "integrity": "sha512-21GCeC9AIIa22uD0Vtqn/N0D5kOB4rY/Pa9aQhxVeLN+4f8Eu4nmteXhFypUD0LL1/58dmm8lS5embsfoIGjEA==", - "dev": true, - "requires": { - "apollo-server-env": "^2.4.5", - "apollo-server-plugin-base": "^0.10.1" - } - }, "apollo-datasource": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.2.tgz", @@ -2660,15 +2289,6 @@ "apollo-server-env": "^2.4.5" } }, - "apollo-engine-reporting-protobuf": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz", - "integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==", - "dev": true, - "requires": { - "@apollo/protobufjs": "^1.0.3" - } - }, "apollo-env": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz", @@ -2703,15 +2323,6 @@ "zen-observable-ts": "^0.8.21" } }, - "apollo-reporting-protobuf": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.0.tgz", - "integrity": "sha512-AFLQIuO0QhkoCF+41Be/B/YU0C33BZ0opfyXorIjM3MNNiEDSyjZqmUozlB3LqgfhT9mn2IR5RSsA+1b4VovDQ==", - "dev": true, - "requires": { - "@apollo/protobufjs": "^1.0.3" - } - }, "apollo-server-caching": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz", @@ -2721,116 +2332,6 @@ "lru-cache": "^5.0.0" } }, - "apollo-server-core": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.18.2.tgz", - "integrity": "sha512-phz57BFBukMa3Ta7ZVW7pj1pdUne9KYLbcBdEcITr+I0+nbhy+YM8gcgpOnjrokWYiEZgIe52XeM3m4BMLw5dg==", - "dev": true, - "requires": { - "@apollographql/apollo-tools": "^0.4.3", - "@apollographql/graphql-playground-html": "1.6.26", - "@types/graphql-upload": "^8.0.0", - "@types/ws": "^7.0.0", - "apollo-cache-control": "^0.11.3", - "apollo-datasource": "^0.7.2", - "apollo-graphql": "^0.6.0", - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5", - "apollo-server-errors": "^2.4.2", - "apollo-server-plugin-base": "^0.10.1", - "apollo-server-types": "^0.6.0", - "apollo-tracing": "^0.11.4", - "async-retry": "^1.2.1", - "fast-json-stable-stringify": "^2.0.0", - "graphql-extensions": "^0.12.5", - "graphql-tag": "^2.9.2", - "graphql-tools": "^4.0.0", - "graphql-upload": "^8.0.2", - "loglevel": "^1.6.7", - "lru-cache": "^5.0.0", - "sha.js": "^2.4.11", - "subscriptions-transport-ws": "^0.9.11", - "uuid": "^8.0.0", - "ws": "^6.0.0" - }, - "dependencies": { - "apollo-server-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.0.tgz", - "integrity": "sha512-usqXaz81bHxD2IZvKEQNnLpSbf2Z/BmobXZAjEefJEQv1ItNn+lJNUmSSEfGejHvHlg2A7WuAJKJWyDWcJrNnA==", - "dev": true, - "requires": { - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - }, - "graphql-upload": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", - "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", - "dev": true, - "requires": { - "busboy": "^0.3.1", - "fs-capacitor": "^2.0.4", - "http-errors": "^1.7.3", - "object-path": "^0.11.4" - }, - "dependencies": { - "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "dev": true, - "requires": { - "dicer": "0.3.0" - } - }, - "object-path": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.5.tgz", - "integrity": "sha512-jgSbThcoR/s+XumvGMTMf81QVBmah+/Q7K7YduKeKVWL7N111unR2d6pZZarSk6kY/caeNxUDyxOvMWyzoU2eg==", - "dev": true - } - } - }, - "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "dev": true - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, "apollo-server-env": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz", @@ -2847,73 +2348,6 @@ "integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ==", "dev": true }, - "apollo-server-express": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.17.0.tgz", - "integrity": "sha512-PonpWOuM1DH3Cz0bu56Tusr3GXOnectC6AD/gy2GXK0v84E7tKTuxEY3SgsgxhvfvvhfwJbXTyIogL/wezqnCw==", - "dev": true, - "requires": { - "@apollographql/graphql-playground-html": "1.6.26", - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.0", - "@types/cors": "^2.8.4", - "@types/express": "4.17.7", - "accepts": "^1.3.5", - "apollo-server-core": "^2.17.0", - "apollo-server-types": "^0.5.1", - "body-parser": "^1.18.3", - "cors": "^2.8.4", - "express": "^4.17.1", - "graphql-subscriptions": "^1.0.0", - "graphql-tools": "^4.0.0", - "parseurl": "^1.3.2", - "subscriptions-transport-ws": "^0.9.16", - "type-is": "^1.6.16" - } - }, - "apollo-server-plugin-base": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.10.1.tgz", - "integrity": "sha512-XChCBDNyfByWqVXptsjPwrwrCj5cxMmNbchZZi8KXjtJ0hN2C/9BMNlInJd6bVGXvUbkRJYUakfKCfO5dZmwIg==", - "dev": true, - "requires": { - "apollo-server-types": "^0.6.0" - }, - "dependencies": { - "apollo-server-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.0.tgz", - "integrity": "sha512-usqXaz81bHxD2IZvKEQNnLpSbf2Z/BmobXZAjEefJEQv1ItNn+lJNUmSSEfGejHvHlg2A7WuAJKJWyDWcJrNnA==", - "dev": true, - "requires": { - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - } - } - }, - "apollo-server-types": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz", - "integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==", - "dev": true, - "requires": { - "apollo-engine-reporting-protobuf": "^0.5.2", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - }, - "apollo-tracing": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.4.tgz", - "integrity": "sha512-zBu/SwQlXfbdpcKLzWARGVjrEkIZUW3W9Mb4CCIzv07HbBQ8IQpmf9w7HIJJefC7rBiBJYg6JBGyuro3N2lxCA==", - "dev": true, - "requires": { - "apollo-server-env": "^2.4.5", - "apollo-server-plugin-base": "^0.10.1" - } - }, "apollo-upload-client": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-14.1.2.tgz", @@ -4208,6 +3642,12 @@ } } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -4217,6 +3657,59 @@ "restore-cursor": "^3.1.0" } }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, "cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -4444,6 +3937,12 @@ "integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==", "dev": true }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -4583,6 +4082,39 @@ "vary": "^1" } }, + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "dependencies": { + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -4724,7 +4256,8 @@ "crypto-js": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", - "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", + "optional": true }, "cssfilter": { "version": "0.0.10", @@ -4829,6 +4362,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -5350,6 +4889,23 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -6259,6 +5815,15 @@ "locate-path": "^3.0.0" } }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, "findup-sync": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", @@ -6543,6 +6108,12 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -6770,30 +6341,6 @@ "integrity": "sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==", "dev": true }, - "graphql-extensions": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.5.tgz", - "integrity": "sha512-mGyGaktGpK3TVBtM0ZoyPX6Xk0mN9GYX9DRyFzDU4k4A2w93nLX7Ebcp+9/O5nHRmgrc0WziYYSmoWq2WNIoUQ==", - "dev": true, - "requires": { - "@apollographql/apollo-tools": "^0.4.3", - "apollo-server-env": "^2.4.5", - "apollo-server-types": "^0.6.0" - }, - "dependencies": { - "apollo-server-types": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.0.tgz", - "integrity": "sha512-usqXaz81bHxD2IZvKEQNnLpSbf2Z/BmobXZAjEefJEQv1ItNn+lJNUmSSEfGejHvHlg2A7WuAJKJWyDWcJrNnA==", - "dev": true, - "requires": { - "apollo-reporting-protobuf": "^0.6.0", - "apollo-server-caching": "^0.5.2", - "apollo-server-env": "^2.4.5" - } - } - } - }, "graphql-list-fields": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/graphql-list-fields/-/graphql-list-fields-2.0.2.tgz", @@ -6807,6 +6354,14 @@ "dev": true, "requires": { "prettier": "^1.16.0" + }, + "dependencies": { + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + } } }, "graphql-subscriptions": { @@ -7446,70 +7001,200 @@ } } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "husky": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.5.tgz", + "integrity": "sha512-E5S/1HMoDDaqsH8kDF5zeKEQbYqe3wL9zJDyqyYqc8I4vHBtAoxkDBGXox0lZ9RI+k5GyB728vZdmnM4bYap+g==", "dev": true, "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "dev": true - }, - "inflight": { - "version": "1.0.6", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true + }, + "inflight": { + "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, @@ -7868,6 +7553,12 @@ } } }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -7904,6 +7595,12 @@ "has-symbols": "^1.0.1" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -8902,6 +8599,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -9003,21 +8706,6 @@ "safe-buffer": "^5.0.1" } }, - "jwks-rsa": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.9.0.tgz", - "integrity": "sha512-UPCfQQg0s2kF2Ju6UFJrQH73f7MaVN/hKBnYBYOp+X9KN4y6TLChhLtaXS5nRKbZqshwVdrZ9OY63m/Q9CLqcg==", - "dev": true, - "requires": { - "@types/express-jwt": "0.0.42", - "axios": "^0.19.2", - "debug": "^4.1.0", - "jsonwebtoken": "^8.5.1", - "limiter": "^1.1.5", - "lru-memoizer": "^2.1.2", - "ms": "^2.1.2" - } - }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -9102,22 +8790,6 @@ "assert-plus": "^1.0.0" } }, - "ldapjs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.1.1.tgz", - "integrity": "sha512-XzF2BEGeM/nenYDAJvkDMYovZ07fIGalrYD+suprSqUWPCWpoa+a4vWl5g8o/En85m6NHWBpirDFNClWLAd77w==", - "dev": true, - "requires": { - "abstract-logging": "^2.0.0", - "asn1": "^0.2.4", - "assert-plus": "^1.0.0", - "backoff": "^2.5.0", - "ldap-filter": "^0.3.3", - "once": "^1.4.0", - "vasync": "^2.2.0", - "verror": "^1.8.1" - } - }, "lead": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", @@ -9180,6 +8852,12 @@ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", "dev": true }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -9189,79 +8867,357 @@ "uc.micro": "^1.0.1" } }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "lint-staged": { + "version": "10.5.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.5.3.tgz", + "integrity": "sha512-TanwFfuqUBLufxCc3RUtFEkFraSPNR3WzWcGF39R3f2J7S9+iF9W0KTVLfSy09lYGmZS5NDCxjNvhGMSJyFCWg==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", - "dev": true - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", - "dev": true - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", - "dev": true - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.2.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.2.0", + "dedent": "^0.7.0", + "enquirer": "^2.3.6", + "execa": "^4.1.0", + "listr2": "^3.2.2", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "listr2": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.2.3.tgz", + "integrity": "sha512-vUb80S2dSUi8YxXahO8/I/s29GqnOL8ozgHVLjfWQXa03BNEeS1TpBLjh2ruaqq5ufx46BRGvfymdBSuoXET5w==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "figures": "^3.2.0", + "indent-string": "^4.0.0", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rxjs": "^6.6.3", + "through": "^2.3.8" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", + "dev": true + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", + "dev": true + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", + "dev": true + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", "dev": true }, @@ -9277,6 +9233,141 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "logform": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", @@ -9796,20 +9887,6 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", "dev": true }, - "mongodb": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", - "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", - "dev": true, - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9984,18 +10061,6 @@ "path-key": "^2.0.0" } }, - "npmlog": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz", - "integrity": "sha1-0DlQ4OeM4VJ7om0qdZLpNIrD518=", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.1", - "set-blocking": "~2.0.0" - } - }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -10225,6 +10290,12 @@ "mimic-fn": "^2.1.0" } }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, "optimism": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.13.1.tgz", @@ -10311,6 +10382,15 @@ "p-limit": "^2.0.0" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", @@ -10345,276 +10425,883 @@ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "^5.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "https-proxy-agent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", + "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "dev": true, + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse-server": { + "version": "github:parse-community/parse-server#06cb79e6a595aefc05f3c4d28f6edcba607f39f5", + "from": "github:parse-community/parse-server#master", + "dev": true, + "requires": { + "@apollographql/graphql-playground-html": "1.6.26", + "@graphql-tools/links": "6.2.5", + "@graphql-tools/stitch": "6.2.4", + "@graphql-tools/utils": "6.2.4", + "@node-rs/bcrypt": "0.4.1", + "@parse/fs-files-adapter": "1.2.0", + "@parse/push-adapter": "3.4.0", + "@parse/s3-files-adapter": "1.6.0", + "@parse/simple-mailgun-adapter": "1.1.0", + "apollo-server-express": "2.19.0", + "bcryptjs": "2.4.3", + "body-parser": "1.19.0", + "commander": "5.1.0", + "cors": "2.8.5", + "deepcopy": "2.1.0", + "express": "4.17.1", + "follow-redirects": "1.13.0", + "graphql": "15.4.0", + "graphql-list-fields": "2.0.2", + "graphql-relay": "0.6.0", + "graphql-upload": "11.0.0", + "intersect": "1.0.1", + "jsonwebtoken": "8.5.1", + "jwks-rsa": "1.11.0", + "ldapjs": "2.2.2", + "lodash": "4.17.20", + "lru-cache": "5.1.1", + "mime": "2.4.6", + "mongodb": "3.6.3", + "parse": "2.18.0", + "pg-promise": "10.8.1", + "pluralize": "8.0.0", + "redis": "3.0.2", + "semver": "7.3.2", + "subscriptions-transport-ws": "0.9.18", + "tv4": "1.3.0", + "uuid": "8.3.1", + "winston": "3.3.3", + "winston-daily-rotate-file": "4.5.0", + "ws": "7.4.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", + "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", + "dev": true, + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, + "@graphql-tools/batch-delegate": { + "version": "6.2.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-delegate/-/batch-delegate-6.2.6.tgz", + "integrity": "sha512-QUoE9pQtkdNPFdJHSnBhZtUfr3M7pIRoXoMR+TG7DK2Y62ISKbT/bKtZEUU1/2v5uqd5WVIvw9dF8gHDSJAsSA==", + "dev": true, + "requires": { + "@graphql-tools/delegate": "^6.2.4", + "dataloader": "2.0.0", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/delegate": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-6.2.4.tgz", + "integrity": "sha512-mXe6DfoWmq49kPcDrpKHgC2DSWcD5q0YCaHHoXYPAOlnLH8VMTY8BxcE8y/Do2eyg+GLcwAcrpffVszWMwqw0w==", + "dev": true, + "requires": { + "@ardatan/aggregate-error": "0.0.6", + "@graphql-tools/schema": "^6.2.4", + "@graphql-tools/utils": "^6.2.4", + "dataloader": "2.0.0", + "is-promise": "4.0.0", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/merge": { + "version": "6.2.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.6.tgz", + "integrity": "sha512-G6x0QlIzFHoJ3dyF9a4gxmBtaEYJ+EoAAGqXHsE/drRr58K1jscQdfKZdF1wZWZgxkgakHqgt1+oFMeQg/O6ug==", + "dev": true, + "requires": { + "@graphql-tools/schema": "^7.0.0", + "@graphql-tools/utils": "^7.0.0", + "tslib": "~2.0.1" + }, + "dependencies": { + "@graphql-tools/schema": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-7.1.2.tgz", + "integrity": "sha512-GabNT51ErVHE2riDH4EQdRusUsI+nMElT8LdFHyuP53v8gwtleAj+LePQ9jif4NYUe/JQVqO8V28vPcHrA7gfQ==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^7.1.2", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/utils": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.1.4.tgz", + "integrity": "sha512-4lxmstMpgHSM1ULD+1X5AcPFaizkdBubB7H9Rqr7Wh6L9bxUHBHFB3bhaFXT7FI0xE01Pt0IMsZadOIlhVTXrg==", + "dev": true, + "requires": { + "@ardatan/aggregate-error": "0.0.6", + "camel-case": "4.1.2", + "tslib": "~2.0.1" + } + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + } } }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "@graphql-tools/schema": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-6.2.4.tgz", + "integrity": "sha512-rh+14lSY1q8IPbEv2J9x8UBFJ5NrDX9W5asXEUlPp+7vraLp/Tiox4GXdgyA92JhwpYco3nTf5Bo2JDMt1KnAQ==", "dev": true, "requires": { - "agent-base": "4", - "debug": "3.1.0" + "@graphql-tools/utils": "^6.2.4", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/stitch": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/stitch/-/stitch-6.2.4.tgz", + "integrity": "sha512-0C7PNkS7v7iAc001m7c1LPm5FUB0/DYw+s3OyCii6YYYHY8NwdI0roeOyeDGFJkFubWBQfjc3hoSyueKtU73mw==", + "dev": true, + "requires": { + "@graphql-tools/batch-delegate": "^6.2.4", + "@graphql-tools/delegate": "^6.2.4", + "@graphql-tools/merge": "^6.2.4", + "@graphql-tools/schema": "^6.2.4", + "@graphql-tools/utils": "^6.2.4", + "@graphql-tools/wrap": "^6.2.4", + "is-promise": "4.0.0", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/utils": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-6.2.4.tgz", + "integrity": "sha512-ybgZ9EIJE3JMOtTrTd2VcIpTXtDrn2q6eiYkeYMKRVh3K41+LZa6YnR2zKERTXqTWqhobROwLt4BZbw2O3Aeeg==", + "dev": true, + "requires": { + "@ardatan/aggregate-error": "0.0.6", + "camel-case": "4.1.1", + "tslib": "~2.0.1" + } + }, + "@graphql-tools/wrap": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-6.2.4.tgz", + "integrity": "sha512-cyQgpybolF9DjL2QNOvTS1WDCT/epgYoiA8/8b3nwv5xmMBQ6/6nYnZwityCZ7njb7MMyk7HBEDNNlP9qNJDcA==", + "dev": true, + "requires": { + "@graphql-tools/delegate": "^6.2.4", + "@graphql-tools/schema": "^6.2.4", + "@graphql-tools/utils": "^6.2.4", + "is-promise": "4.0.0", + "tslib": "~2.0.1" + } + }, + "@parse/fs-files-adapter": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.0.tgz", + "integrity": "sha512-kr7Ti2eYOm14p05S86yriJdMtawL6qln3Dn5eekrwY14ih4jrjH/E+QlEpBUSBzN64fluFxciFOyjdbwDGWsGw==", + "dev": true + }, + "@parse/node-apn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.0.0.tgz", + "integrity": "sha512-/Zhz7+AfwuMeBn9kpENF5qbWDG1+0xLBOlAb7O34BhR9R5BSjAKkMxqWmTz3R3nvlsod4XrZ8NuRMUOXVrCCFQ==", + "dev": true, + "requires": { + "debug": "3.1.0", + "jsonwebtoken": "8.1.0", + "node-forge": "0.10.0", + "verror": "1.10.0" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "jsonwebtoken": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", + "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", "dev": true, "requires": { - "ms": "2.0.0" + "jws": "^3.1.4", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.0.0", + "xtend": "^4.0.1" + } + } + } + }, + "@parse/push-adapter": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.0.tgz", + "integrity": "sha512-ZYf6DKQHpUoi806SIDiuVhstL3BRQC4brcCyTnoLih/u08Cg60Pbkz2B95JU+6xMcM211A2AvPDudEmsMahq7w==", + "dev": true, + "requires": { + "@parse/node-apn": "4.0.0", + "@parse/node-gcm": "1.0.2", + "npmlog": "4.1.2", + "parse": "2.17.0" + }, + "dependencies": { + "parse": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", + "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", + "dev": true, + "requires": { + "@babel/runtime": "7.11.2", + "@babel/runtime-corejs3": "7.11.2", + "crypto-js": "4.0.0", + "react-native-crypto-js": "1.0.0", + "uuid": "3.4.0", + "ws": "7.3.1", + "xmlhttprequest": "1.8.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true + } + } + }, + "@parse/s3-files-adapter": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@parse/s3-files-adapter/-/s3-files-adapter-1.6.0.tgz", + "integrity": "sha512-t/91hlZ4+GIA68zmJIX9lkIAxPZVRJROPYWGGyxE9CLGsSvBr/eaIHs6LnKyM012lBHzwJwoLxMkN4RvJADgbg==", + "dev": true, + "requires": { + "aws-sdk": "2.761.0", + "parse": "2.17.0" + }, + "dependencies": { + "parse": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-2.17.0.tgz", + "integrity": "sha512-1hWoMNW39LH5YV3xCds9LyD8SsKD6FUwlD1Kn8ZlXNosg6WgF+s3ZSQUzT5AJ/9YPUoC/y1PoCO79FumrBYftA==", + "dev": true, + "requires": { + "@babel/runtime": "7.11.2", + "@babel/runtime-corejs3": "7.11.2", + "crypto-js": "4.0.0", + "react-native-crypto-js": "1.0.0", + "uuid": "3.4.0", + "ws": "7.3.1", + "xmlhttprequest": "1.8.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "dev": true + } + } + }, + "apollo-cache-control": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.4.tgz", + "integrity": "sha512-FUKE8ASr8GxVq5rmky/tY8bsf++cleGT591lfLiqnPsP1fo3kAfgRfWA2QRHTCKFNlQxzUhVOEDv+PaysqiOjw==", + "dev": true, + "requires": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.10.2" + } + }, + "apollo-reporting-protobuf": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.1.tgz", + "integrity": "sha512-qr4DheFP154PGZsd93SSIS9RkqHnR5b6vT+eCloWjy3UIpY+yZ3cVLlttlIjYvOG4xTJ25XEwcHiAExatQo/7g==", + "dev": true, + "requires": { + "@apollo/protobufjs": "^1.0.3" + } + }, + "apollo-server-core": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.19.0.tgz", + "integrity": "sha512-2aMKUVPyNbomJQaG2tkpfqvp1Tfgxgkdr7nX5zHudYNSzsPrHw+CcYlCbIVFFI/mTZsjoK9czNq1qerFRxZbJw==", + "dev": true, + "requires": { + "@apollographql/apollo-tools": "^0.4.3", + "@apollographql/graphql-playground-html": "1.6.26", + "@types/graphql-upload": "^8.0.0", + "@types/ws": "^7.0.0", + "apollo-cache-control": "^0.11.4", + "apollo-datasource": "^0.7.2", + "apollo-graphql": "^0.6.0", + "apollo-reporting-protobuf": "^0.6.1", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5", + "apollo-server-errors": "^2.4.2", + "apollo-server-plugin-base": "^0.10.2", + "apollo-server-types": "^0.6.1", + "apollo-tracing": "^0.12.0", + "async-retry": "^1.2.1", + "fast-json-stable-stringify": "^2.0.0", + "graphql-extensions": "^0.12.6", + "graphql-tag": "^2.9.2", + "graphql-tools": "^4.0.0", + "graphql-upload": "^8.0.2", + "loglevel": "^1.6.7", + "lru-cache": "^5.0.0", + "sha.js": "^2.4.11", + "subscriptions-transport-ws": "^0.9.11", + "uuid": "^8.0.0", + "ws": "^6.0.0" + }, + "dependencies": { + "graphql-upload": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.1.0.tgz", + "integrity": "sha512-U2OiDI5VxYmzRKw0Z2dmfk0zkqMRaecH9Smh1U277gVgVe9Qn+18xqf4skwr4YJszGIh7iQDZ57+5ygOK9sM/Q==", + "dev": true, + "requires": { + "busboy": "^0.3.1", + "fs-capacitor": "^2.0.4", + "http-errors": "^1.7.3", + "object-path": "^0.11.4" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" } } } }, + "apollo-server-express": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.19.0.tgz", + "integrity": "sha512-3rgSrTme1SlLoecAYtSa8ThH6vYvz29QecgZCigq5Vdc6bFP2SZrCk0ls6BAdD8OZbVKUtizzRxd0yd/uREPAw==", + "dev": true, + "requires": { + "@apollographql/graphql-playground-html": "1.6.26", + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.0", + "@types/cors": "2.8.8", + "@types/express": "4.17.7", + "@types/express-serve-static-core": "4.17.13", + "accepts": "^1.3.5", + "apollo-server-core": "^2.19.0", + "apollo-server-types": "^0.6.1", + "body-parser": "^1.18.3", + "cors": "^2.8.4", + "express": "^4.17.1", + "graphql-subscriptions": "^1.0.0", + "graphql-tools": "^4.0.0", + "parseurl": "^1.3.2", + "subscriptions-transport-ws": "^0.9.16", + "type-is": "^1.6.16" + } + }, + "apollo-server-plugin-base": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.10.2.tgz", + "integrity": "sha512-uM5uL1lOxbXdgvt/aEIbgs40fV9xA45Y3Mmh0VtQ/ddqq0MXR5aG92nnf8rM+URarBCUfxKJKaYzJJ/CXAnEdA==", + "dev": true, + "requires": { + "apollo-server-types": "^0.6.1" + } + }, + "apollo-server-types": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.1.tgz", + "integrity": "sha512-IEQ37aYvMLiTUzsySVLOSuvvhxuyYdhI05f3cnH6u2aN1HgGp7vX6bg+U3Ue8wbHfdcifcGIk5UEU+Q+QO6InA==", + "dev": true, + "requires": { + "apollo-reporting-protobuf": "^0.6.1", + "apollo-server-caching": "^0.5.2", + "apollo-server-env": "^2.4.5" + } + }, + "apollo-tracing": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.12.0.tgz", + "integrity": "sha512-cMUYGE6mOEwb9HDqhf4fiPEo2JMhjPIqEprAQEC57El76avRpRig5NM0bnqMZcYJZR5QmLlNcttNccOwf9WrNg==", + "dev": true, + "requires": { + "apollo-server-env": "^2.4.5", + "apollo-server-plugin-base": "^0.10.2" + } + }, + "camel-case": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", + "dev": true, + "requires": { + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "graphql": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.4.0.tgz", + "integrity": "sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==", + "dev": true + }, + "graphql-extensions": { + "version": "0.12.6", + "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.6.tgz", + "integrity": "sha512-EUNw+OIRXYTPxToSoJjhJvS5aGa94KkdkZnL1I9DCZT64/+rzQNeLeGj+goj2RYuYvoQe1Bmcx0CNZ1GqwBhng==", + "dev": true, + "requires": { + "@apollographql/apollo-tools": "^0.4.3", + "apollo-server-env": "^2.4.5", + "apollo-server-types": "^0.6.1" + } + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, "https-proxy-agent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz", - "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dev": true, "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" + "agent-base": "6", + "debug": "4" }, "dependencies": { "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "jwks-rsa": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.11.0.tgz", + "integrity": "sha512-G7ZgXZ3dlGbOUBQwgF+U/SVzOlI9KxJ9Uzp61bue2S5TV0h7c+kJRCl3bEPkC5PVmeu7/h82B3uQALVJMjzt/Q==", + "dev": true, + "requires": { + "@types/express-jwt": "0.0.42", + "axios": "^0.19.2", + "debug": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jsonwebtoken": "^8.5.1", + "limiter": "^1.1.5", + "lru-memoizer": "^2.1.2", + "ms": "^2.1.2", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "ldapjs": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.2.2.tgz", + "integrity": "sha512-PgMVYKWUjkkK6v81QQc+kKsr4TcKRggYuvjwo1h4ZEhaXGIkhLvcK9Y60nZqR5RRvyYbt8Ott1VyN7S5EiYArA==", + "dev": true, + "requires": { + "abstract-logging": "^2.0.0", + "asn1": "^0.2.4", + "assert-plus": "^1.0.0", + "backoff": "^2.5.0", + "ldap-filter": "^0.3.3", + "once": "^1.4.0", + "vasync": "^2.2.0", + "verror": "^1.8.1" + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "mongodb": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "dev": true, + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "parse": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-2.18.0.tgz", + "integrity": "sha512-RaSLhcpTZIaITanJY3YzVASyLaCTBh0v4Bq0M3nrKGQXWa9/iscWtidPhV6xpSBzat53aqO4eL3L5J1zwZzsUg==", + "dev": true, + "requires": { + "@babel/runtime": "7.12.1", + "@babel/runtime-corejs3": "7.12.1", + "crypto-js": "4.0.0", + "react-native-crypto-js": "1.0.0", + "uuid": "3.4.0", + "ws": "7.3.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", + "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.12.1.tgz", + "integrity": "sha512-umhPIcMrlBZ2aTWlWjUseW9LjQKxi1dpFlQS8DzsxB//5K+u6GLTC/JliPKHsd5kJVPIU6X/Hy0YvWOYPcMxBw==", "dev": true, "requires": { - "ms": "^2.1.1" + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "ws": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", "dev": true } } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "pac-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", - "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", - "dev": true, - "requires": { - "co": "^4.6.0", - "degenerator": "^1.0.4", - "ip": "^1.1.5", - "netmask": "^1.0.6", - "thunkify": "^2.1.2" - } - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-2.15.0.tgz", - "integrity": "sha512-Aupg+qd6I4X5uTacpsxROg5GlhkVn2+qOHtyOhlGj/Woi75c5cPD8kn7qhhLKcVVpe2L+HoJ+yGkMdI8IjKBKA==", - "dev": true, - "requires": { - "@babel/runtime": "7.10.3", - "@babel/runtime-corejs3": "7.10.3", - "crypto-js": "4.0.0", - "react-native-crypto-js": "1.0.0", - "uuid": "3.4.0", - "ws": "7.3.0", - "xmlhttprequest": "1.8.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.3.tgz", - "integrity": "sha512-RzGO0RLSdokm9Ipe/YD+7ww8X2Ro79qiXZF3HU9ljrM+qnJmH1Vqth+hbiQZy761LnMJTMitHDuKVYTk3k4dLw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz", - "integrity": "sha512-HA7RPj5xvJxQl429r5Cxr2trJwOfPjKiqhCXcdQPSqO2G0RHPZpXu4fkYmBaTKCp2c/jRaMK9GB/lN+7zvvFPw==", + "pg": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", + "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", "dev": true, "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.4.0", + "pg-pool": "^3.2.2", + "pg-protocol": "^1.4.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" } }, - "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", - "dev": true - } - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "pg-pool": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", + "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==", "dev": true }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "pg-promise": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.8.1.tgz", + "integrity": "sha512-xRW3PBopAAPlSmOutfpxwrd0i1wfiVoJjkRC2xYzwk0PwWGLEOVKoDEHX4VoqjfIJ+SEEiILy5B5nUVvXpFFVA==", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "assert-options": "0.6.2", + "pg": "8.5.1", + "pg-minify": "1.6.1", + "spex": "3.0.2" } - } - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-server": { - "version": "github:parse-community/parse-server#06cb79e6a595aefc05f3c4d28f6edcba607f39f5", - "from": "github:parse-community/parse-server#master", - "dev": true, - "requires": { - "@apollographql/graphql-playground-html": "1.6.26", - "@graphql-tools/links": "^6.2.4", - "@graphql-tools/stitch": "6.2.2", - "@graphql-tools/utils": "6.2.2", - "@node-rs/bcrypt": "0.4.1", - "@parse/fs-files-adapter": "1.0.1", - "@parse/push-adapter": "3.3.0", - "@parse/s3-files-adapter": "1.5.0", - "@parse/simple-mailgun-adapter": "1.1.0", - "apollo-server-express": "2.17.0", - "bcryptjs": "2.4.3", - "body-parser": "1.19.0", - "commander": "5.1.0", - "cors": "2.8.5", - "deepcopy": "2.1.0", - "express": "4.17.1", - "follow-redirects": "1.13.0", - "graphql": "15.3.0", - "graphql-list-fields": "2.0.2", - "graphql-relay": "0.6.0", - "graphql-upload": "11.0.0", - "intersect": "1.0.1", - "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.9.0", - "ldapjs": "2.1.1", - "lodash": "4.17.20", - "lru-cache": "5.1.1", - "mime": "2.4.6", - "mongodb": "3.6.2", - "parse": "2.15.0", - "pg-promise": "10.6.1", - "pluralize": "8.0.0", - "redis": "3.0.2", - "semver": "7.3.2", - "subscriptions-transport-ws": "0.9.18", - "tv4": "1.3.0", - "uuid": "8.3.0", - "winston": "3.3.3", - "winston-daily-rotate-file": "4.5.0", - "ws": "7.3.1" - }, - "dependencies": { - "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + }, + "pg-protocol": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", + "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==", "dev": true }, "semver": { @@ -10623,16 +11310,28 @@ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "dev": true + }, "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", "dev": true }, "ws": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", - "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", + "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==", "dev": true } } @@ -10781,30 +11480,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "pg": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.3.tgz", - "integrity": "sha512-wmUyoQM/Xzmo62wgOdQAn5tl7u+IA1ZYK7qbuppi+3E+Gj4hlUxVHjInulieWrd0SfHi/ADriTb5ILJ/lsJrSg==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.3.0", - "pg-pool": "^3.2.1", - "pg-protocol": "^1.2.5", - "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "dependencies": { - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", - "dev": true - } - } - }, "pg-connection-string": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", @@ -10823,30 +11498,6 @@ "integrity": "sha512-ujanxJJB9CSDUvlAOshtjdKAywOPR2vY0a7D+vvgk5rbrYcthZA7TjpN+Z+UwZsz/G/bUexYDT6huE33vYVN0g==", "dev": true }, - "pg-pool": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", - "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==", - "dev": true - }, - "pg-promise": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.6.1.tgz", - "integrity": "sha512-Ahde0/04RmEPwryMcDV8ya4XXjfNWD44EuckgFPFQOIX/3smZS2ygeSXPEy4DmDxoSkSF6Y6vK8Bc4fN+bYMxg==", - "dev": true, - "requires": { - "assert-options": "0.6.2", - "pg": "8.3.3", - "pg-minify": "1.6.1", - "spex": "3.0.2" - } - }, - "pg-protocol": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.3.0.tgz", - "integrity": "sha512-64/bYByMrhWULUaCd+6/72c9PMWhiVFs3EVxl9Ct6a3v/U8+rKgqP2w+kKg/BIGgMJyB+Bk/eNivT32Al+Jghw==", - "dev": true - }, "pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", @@ -10869,6 +11520,12 @@ "split": "^1.0.0" } }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -10908,6 +11565,15 @@ "find-up": "^3.0.0" } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", @@ -10984,9 +11650,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", "dev": true }, "pretty-format": { @@ -11871,6 +12537,12 @@ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, "semver-greatest-satisfied-range": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", @@ -11880,6 +12552,12 @@ "sver-compat": "^1.5.0" } }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -12548,6 +13226,12 @@ "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", "dev": true }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -12682,6 +13366,17 @@ } } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -12732,6 +13427,12 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -13734,6 +14435,12 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -14011,6 +14718,12 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, "yargs": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", diff --git a/package.json b/package.json index f3d3036a6..ca8b02b63 100644 --- a/package.json +++ b/package.json @@ -65,13 +65,16 @@ "gulp-rename": "2.0.0", "gulp-uglify": "3.0.2", "gulp-watch": "5.0.1", + "husky": "4.3.5", "jasmine": "3.5.0", "jasmine-reporters": "2.3.2", "jest": "24.9.0", "jsdoc": "3.6.3", "jsdoc-babel": "0.5.0", + "lint-staged": "10.5.3", "metro-react-native-babel-preset": "0.59.0", "parse-server": "github:parse-community/parse-server#master", + "prettier": "2.2.1", "regenerator-runtime": "0.13.5", "vinyl-source-stream": "2.0.0" }, @@ -93,8 +96,20 @@ "prepare": "npm run build", "release_docs": "./release_docs.sh", "gulp": "gulp", + "prettier": "prettier --write {src,integration}/{**/*,*}.js && npm run lint:fix", "cross-env": "cross-env" }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "{src,integration}/{**/*,*}.js": [ + "prettier", + "git add" + ] + }, "jest": { "automock": true, "collectCoverage": true, diff --git a/src/Analytics.js b/src/Analytics.js index c0ad3c94c..348528077 100644 --- a/src/Analytics.js +++ b/src/Analytics.js @@ -51,10 +51,7 @@ import CoreManager from './CoreManager'; * @returns {Promise} A promise that is resolved when the round-trip * to the server completes. */ -export function track( - name: string, - dimensions: { [key: string]: string } -): Promise { +export function track(name: string, dimensions: { [key: string]: string }): Promise { name = name || ''; name = name.replace(/^\s*/, ''); name = name.replace(/\s*$/, ''); @@ -64,14 +61,11 @@ export function track( for (const key in dimensions) { if (typeof key !== 'string' || typeof dimensions[key] !== 'string') { - throw new TypeError( - 'track() dimensions expects keys and values of type "string".' - ); + throw new TypeError('track() dimensions expects keys and values of type "string".'); } } - return CoreManager.getAnalyticsController() - .track(name, dimensions); + return CoreManager.getAnalyticsController().track(name, dimensions); } const DefaultController = { @@ -79,7 +73,7 @@ const DefaultController = { const path = 'events/' + name; const RESTController = CoreManager.getRESTController(); return RESTController.request('POST', path, { dimensions: dimensions }); - } + }, }; CoreManager.setAnalyticsController(DefaultController); diff --git a/src/AnonymousUtils.js b/src/AnonymousUtils.js index 630d18f0f..4c8ce6f81 100644 --- a/src/AnonymousUtils.js +++ b/src/AnonymousUtils.js @@ -112,7 +112,7 @@ const AnonymousUtils = { registered = true; } return provider; - } + }, }; export default AnonymousUtils; diff --git a/src/Cloud.js b/src/Cloud.js index 5471ac740..59797e9fd 100644 --- a/src/Cloud.js +++ b/src/Cloud.js @@ -40,11 +40,7 @@ import type { RequestOptions } from './RESTController'; * @returns {Promise} A promise that will be resolved with the result * of the function. */ -export function run( - name: string, - data: mixed, - options: RequestOptions -): Promise { +export function run(name: string, data: mixed, options: RequestOptions): Promise { options = options || {}; if (typeof name !== 'string' || name.length === 0) { @@ -75,7 +71,7 @@ export function run( */ export function getJobsData(): Promise { const requestOptions = { - useMasterKey: true + useMasterKey: true, }; return CoreManager.getCloudController().getJobsData(requestOptions); } @@ -90,16 +86,12 @@ export function getJobsData(): Promise { * @returns {Promise} A promise that will be resolved with the jobStatusId * of the job. */ -export function startJob( - name: string, - data: mixed, -): Promise { - +export function startJob(name: string, data: mixed): Promise { if (typeof name !== 'string' || name.length === 0) { throw new TypeError('Cloud job name must be a string.'); } const requestOptions = { - useMasterKey: true + useMasterKey: true, }; return CoreManager.getCloudController().startJob(name, data, requestOptions); } @@ -123,21 +115,11 @@ const DefaultController = { const payload = encode(data, true); - const request = RESTController.request( - 'POST', - 'functions/' + name, - payload, - options - ); - - return request.then((res) => { - if (typeof res === 'object' && - Object.keys(res).length > 0 && - !res.hasOwnProperty('result')) { - throw new ParseError( - ParseError.INVALID_JSON, - 'The server returned an invalid response.' - ); + const request = RESTController.request('POST', 'functions/' + name, payload, options); + + return request.then(res => { + if (typeof res === 'object' && Object.keys(res).length > 0 && !res.hasOwnProperty('result')) { + throw new ParseError(ParseError.INVALID_JSON, 'The server returned an invalid response.'); } const decoded = decode(res); if (decoded && decoded.hasOwnProperty('result')) { @@ -150,12 +132,7 @@ const DefaultController = { getJobsData(options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', - 'cloud_code/jobs/data', - null, - options - ); + return RESTController.request('GET', 'cloud_code/jobs/data', null, options); }, startJob(name, data, options: RequestOptions) { @@ -163,13 +140,8 @@ const DefaultController = { const payload = encode(data, true); - return RESTController.request( - 'POST', - 'jobs/' + name, - payload, - options, - ); - } + return RESTController.request('POST', 'jobs/' + name, payload, options); + }, }; CoreManager.setCloudController(DefaultController); diff --git a/src/CloudCode.js b/src/CloudCode.js index 4bdd98706..f25bfa239 100644 --- a/src/CloudCode.js +++ b/src/CloudCode.js @@ -210,7 +210,6 @@ * ``` */ - /** * Makes an HTTP Request. * diff --git a/src/CoreManager.js b/src/CoreManager.js index d402216dc..b6a43bfa6 100644 --- a/src/CoreManager.js +++ b/src/CoreManager.js @@ -21,135 +21,141 @@ import type { PushData } from './Push'; import type { RequestOptions, FullOptions } from './RESTController'; type AnalyticsController = { - track: (name: string, dimensions: { [key: string]: string }) => Promise; + track: (name: string, dimensions: { [key: string]: string }) => Promise, }; type CloudController = { - run: (name: string, data: mixed, options: RequestOptions) => Promise; - getJobsData: (options: RequestOptions) => Promise; - startJob: (name: string, data: mixed, options: RequestOptions) => Promise; + run: (name: string, data: mixed, options: RequestOptions) => Promise, + getJobsData: (options: RequestOptions) => Promise, + startJob: (name: string, data: mixed, options: RequestOptions) => Promise, }; type ConfigController = { - current: () => Promise; - get: () => Promise; - save: (attrs: { [key: string]: any }) => Promise; + current: () => Promise, + get: () => Promise, + save: (attrs: { [key: string]: any }) => Promise, }; type CryptoController = { - encrypt: (obj: any, secretKey: string) => string; - decrypt: (encryptedText: string, secretKey: any) => string; + encrypt: (obj: any, secretKey: string) => string, + decrypt: (encryptedText: string, secretKey: any) => string, }; type FileController = { - saveFile: (name: string, source: FileSource, options: FullOptions) => Promise; - saveBase64: (name: string, source: FileSource, options: FullOptions) => Promise; - download: (uri: string) => Promise; + saveFile: (name: string, source: FileSource, options: FullOptions) => Promise, + saveBase64: (name: string, source: FileSource, options: FullOptions) => Promise, + download: (uri: string) => Promise, }; type InstallationController = { - currentInstallationId: () => Promise; + currentInstallationId: () => Promise, }; type ObjectController = { - fetch: (object: ParseObject | Array, forceFetch: boolean, options: RequestOptions) => Promise; - save: (object: ParseObject | Array, options: RequestOptions) => Promise; - destroy: (object: ParseObject | Array, options: RequestOptions) => Promise; + fetch: ( + object: ParseObject | Array, + forceFetch: boolean, + options: RequestOptions + ) => Promise, + save: (object: ParseObject | Array, options: RequestOptions) => Promise, + destroy: (object: ParseObject | Array, options: RequestOptions) => Promise, }; type ObjectStateController = { - getState: (obj: any) => ?State; - initializeState: (obj: any, initial?: State) => State; - removeState: (obj: any) => ?State; - getServerData: (obj: any) => AttributeMap; - setServerData: (obj: any, attributes: AttributeMap) => void; - getPendingOps: (obj: any) => Array; - setPendingOp: (obj: any, attr: string, op: ?Op) => void; - pushPendingState: (obj: any) => void; - popPendingState: (obj: any) => OpsMap; - mergeFirstPendingState: (obj: any) => void; - getObjectCache: (obj: any) => ObjectCache; - estimateAttribute: (obj: any, attr: string) => mixed; - estimateAttributes: (obj: any) => AttributeMap; - commitServerChanges: (obj: any, changes: AttributeMap) => void; - enqueueTask: (obj: any, task: () => Promise) => Promise; - clearAllState: () => void; - duplicateState: (source: any, dest: any) => void; + getState: (obj: any) => ?State, + initializeState: (obj: any, initial?: State) => State, + removeState: (obj: any) => ?State, + getServerData: (obj: any) => AttributeMap, + setServerData: (obj: any, attributes: AttributeMap) => void, + getPendingOps: (obj: any) => Array, + setPendingOp: (obj: any, attr: string, op: ?Op) => void, + pushPendingState: (obj: any) => void, + popPendingState: (obj: any) => OpsMap, + mergeFirstPendingState: (obj: any) => void, + getObjectCache: (obj: any) => ObjectCache, + estimateAttribute: (obj: any, attr: string) => mixed, + estimateAttributes: (obj: any) => AttributeMap, + commitServerChanges: (obj: any, changes: AttributeMap) => void, + enqueueTask: (obj: any, task: () => Promise) => Promise, + clearAllState: () => void, + duplicateState: (source: any, dest: any) => void, }; type PushController = { - send: (data: PushData) => Promise; + send: (data: PushData) => Promise, }; type QueryController = { - find: (className: string, params: QueryJSON, options: RequestOptions) => Promise; - aggregate: (className: string, params: any, options: RequestOptions) => Promise; + find: (className: string, params: QueryJSON, options: RequestOptions) => Promise, + aggregate: (className: string, params: any, options: RequestOptions) => Promise, }; type RESTController = { - request: (method: string, path: string, data: mixed, options: RequestOptions) => Promise; - ajax: (method: string, url: string, data: any, headers?: any, options: FullOptions) => Promise; + request: (method: string, path: string, data: mixed, options: RequestOptions) => Promise, + ajax: (method: string, url: string, data: any, headers?: any, options: FullOptions) => Promise, }; type SchemaController = { - purge: (className: string) => Promise; - get: (className: string, options: RequestOptions) => Promise; - delete: (className: string, options: RequestOptions) => Promise; - create: (className: string, params: any, options: RequestOptions) => Promise; - update: (className: string, params: any, options: RequestOptions) => Promise; - send(className: string, method: string, params: any, options: RequestOptions): Promise; + purge: (className: string) => Promise, + get: (className: string, options: RequestOptions) => Promise, + delete: (className: string, options: RequestOptions) => Promise, + create: (className: string, params: any, options: RequestOptions) => Promise, + update: (className: string, params: any, options: RequestOptions) => Promise, + send(className: string, method: string, params: any, options: RequestOptions): Promise, }; type SessionController = { - getSession: (token: RequestOptions) => Promise; -}; -type StorageController = { - async: 0; - getItem: (path: string) => ?string; - setItem: (path: string, value: string) => void; - removeItem: (path: string) => void; - getItemAsync?: (path: string) => Promise; - setItemAsync?: (path: string, value: string) => Promise; - removeItemAsync?: (path: string) => Promise; - clear: () => void; -} | { - async: 1; - getItem?: (path: string) => ?string; - setItem?: (path: string, value: string) => void; - removeItem?: (path: string) => void; - getItemAsync: (path: string) => Promise; - setItemAsync: (path: string, value: string) => Promise; - removeItemAsync: (path: string) => Promise; - clear: () => void; + getSession: (token: RequestOptions) => Promise, }; +type StorageController = + | { + async: 0, + getItem: (path: string) => ?string, + setItem: (path: string, value: string) => void, + removeItem: (path: string) => void, + getItemAsync?: (path: string) => Promise, + setItemAsync?: (path: string, value: string) => Promise, + removeItemAsync?: (path: string) => Promise, + clear: () => void, + } + | { + async: 1, + getItem?: (path: string) => ?string, + setItem?: (path: string, value: string) => void, + removeItem?: (path: string) => void, + getItemAsync: (path: string) => Promise, + setItemAsync: (path: string, value: string) => Promise, + removeItemAsync: (path: string) => Promise, + clear: () => void, + }; type LocalDatastoreController = { - fromPinWithName: (name: string) => ?any; - pinWithName: (name: string, objects: any) => void; - unPinWithName: (name: string) => void; - getAllContents: () => ?any; - clear: () => void; + fromPinWithName: (name: string) => ?any, + pinWithName: (name: string, objects: any) => void, + unPinWithName: (name: string) => void, + getAllContents: () => ?any, + clear: () => void, }; type UserController = { - setCurrentUser: (user: ParseUser) => Promise; - currentUser: () => ?ParseUser; - currentUserAsync: () => Promise; - signUp: (user: ParseUser, attrs: AttributeMap, options: RequestOptions) => Promise; - logIn: (user: ParseUser, options: RequestOptions) => Promise; - become: (options: RequestOptions) => Promise; - hydrate: (userJSON: AttributeMap) => Promise; - logOut: (options: RequestOptions) => Promise; - me: (options: RequestOptions) => Promise; - requestPasswordReset: (email: string, options: RequestOptions) => Promise; - updateUserOnDisk: (user: ParseUser) => Promise; - upgradeToRevocableSession: (user: ParseUser, options: RequestOptions) => Promise; - linkWith: (user: ParseUser, authData: AuthData) => Promise; - removeUserFromDisk: () => Promise; - verifyPassword: (username: string, password: string, options: RequestOptions) => Promise; - requestEmailVerification: (email: string, options: RequestOptions) => Promise; + setCurrentUser: (user: ParseUser) => Promise, + currentUser: () => ?ParseUser, + currentUserAsync: () => Promise, + signUp: (user: ParseUser, attrs: AttributeMap, options: RequestOptions) => Promise, + logIn: (user: ParseUser, options: RequestOptions) => Promise, + become: (options: RequestOptions) => Promise, + hydrate: (userJSON: AttributeMap) => Promise, + logOut: (options: RequestOptions) => Promise, + me: (options: RequestOptions) => Promise, + requestPasswordReset: (email: string, options: RequestOptions) => Promise, + updateUserOnDisk: (user: ParseUser) => Promise, + upgradeToRevocableSession: (user: ParseUser, options: RequestOptions) => Promise, + linkWith: (user: ParseUser, authData: AuthData) => Promise, + removeUserFromDisk: () => Promise, + verifyPassword: (username: string, password: string, options: RequestOptions) => Promise, + requestEmailVerification: (email: string, options: RequestOptions) => Promise, }; type HooksController = { - get: (type: string, functionName?: string, triggerName?: string) => Promise; - create: (hook: mixed) => Promise; - delete: (hook: mixed) => Promise; - update: (hook: mixed) => Promise; - send: (method: string, path: string, body?: mixed) => Promise; + get: (type: string, functionName?: string, triggerName?: string) => Promise, + create: (hook: mixed) => Promise, + delete: (hook: mixed) => Promise, + update: (hook: mixed) => Promise, + send: (method: string, path: string, body?: mixed) => Promise, }; type WebSocketController = { - onopen: () => void; - onmessage: (message: any) => void; - onclose: () => void; - onerror: (error: any) => void; - send: (data: any) => void; - close: () => void; -} + onopen: () => void, + onmessage: (message: any) => void, + onclose: () => void, + onerror: (error: any) => void, + send: (data: any) => void, + close: () => void, +}; type Config = { AnalyticsController?: AnalyticsController, CloudController?: CloudController, @@ -172,10 +178,11 @@ type Config = { const config: Config & { [key: string]: mixed } = { // Defaults - IS_NODE: (typeof process !== 'undefined' && - !!process.versions && - !!process.versions.node && - !process.versions.electron), + IS_NODE: + typeof process !== 'undefined' && + !!process.versions && + !!process.versions.node && + !process.versions.electron, REQUEST_ATTEMPT_LIMIT: 5, REQUEST_BATCH_SIZE: 20, REQUEST_HEADERS: {}, @@ -192,11 +199,11 @@ const config: Config & { [key: string]: mixed } = { PERFORM_USER_REWRITE: true, FORCE_REVOCABLE_SESSION: false, ENCRYPTED_USER: false, - IDEMPOTENCY: false + IDEMPOTENCY: false, }; function requireMethods(name: string, methods: Array, controller: any) { - methods.forEach((func) => { + methods.forEach(func => { if (typeof controller[func] !== 'function') { throw new Error(`${name} must implement ${func}()`); } @@ -204,14 +211,14 @@ function requireMethods(name: string, methods: Array, controller: any) { } module.exports = { - get: function(key: string): any { + get: function (key: string): any { if (config.hasOwnProperty(key)) { return config[key]; } throw new Error('Configuration key not found: ' + key); }, - set: function(key: string, value: any): void { + set: function (key: string, value: any): void { config[key] = value; }, @@ -281,24 +288,28 @@ module.exports = { }, setObjectStateController(controller: ObjectStateController) { - requireMethods('ObjectStateController', [ - 'getState', - 'initializeState', - 'removeState', - 'getServerData', - 'setServerData', - 'getPendingOps', - 'setPendingOp', - 'pushPendingState', - 'popPendingState', - 'mergeFirstPendingState', - 'getObjectCache', - 'estimateAttribute', - 'estimateAttributes', - 'commitServerChanges', - 'enqueueTask', - 'clearAllState', - ], controller); + requireMethods( + 'ObjectStateController', + [ + 'getState', + 'initializeState', + 'removeState', + 'getServerData', + 'setServerData', + 'getPendingOps', + 'setPendingOp', + 'pushPendingState', + 'popPendingState', + 'mergeFirstPendingState', + 'getObjectCache', + 'estimateAttribute', + 'estimateAttributes', + 'commitServerChanges', + 'enqueueTask', + 'clearAllState', + ], + controller + ); config['ObjectStateController'] = controller; }, @@ -335,7 +346,11 @@ module.exports = { }, setSchemaController(controller: SchemaController) { - requireMethods('SchemaController', ['get', 'create', 'update', 'delete', 'send', 'purge'], controller); + requireMethods( + 'SchemaController', + ['get', 'create', 'update', 'delete', 'send', 'purge'], + controller + ); config['SchemaController'] = controller; }, @@ -354,25 +369,27 @@ module.exports = { setStorageController(controller: StorageController) { if (controller.async) { - requireMethods('An async StorageController', [ - 'getItemAsync', - 'setItemAsync', - 'removeItemAsync', - 'getAllKeysAsync' - ], controller); + requireMethods( + 'An async StorageController', + ['getItemAsync', 'setItemAsync', 'removeItemAsync', 'getAllKeysAsync'], + controller + ); } else { - requireMethods('A synchronous StorageController', [ - 'getItem', - 'setItem', - 'removeItem', - 'getAllKeys' - ], controller); + requireMethods( + 'A synchronous StorageController', + ['getItem', 'setItem', 'removeItem', 'getAllKeys'], + controller + ); } config['StorageController'] = controller; }, setLocalDatastoreController(controller: LocalDatastoreController) { - requireMethods('LocalDatastoreController', ['pinWithName', 'fromPinWithName', 'unPinWithName', 'getAllContents', 'clear'], controller); + requireMethods( + 'LocalDatastoreController', + ['pinWithName', 'fromPinWithName', 'unPinWithName', 'getAllContents', 'clear'], + controller + ); config['LocalDatastoreController'] = controller; }, @@ -409,21 +426,25 @@ module.exports = { }, setUserController(controller: UserController) { - requireMethods('UserController', [ - 'setCurrentUser', - 'currentUser', - 'currentUserAsync', - 'signUp', - 'logIn', - 'become', - 'logOut', - 'me', - 'requestPasswordReset', - 'upgradeToRevocableSession', - 'requestEmailVerification', - 'verifyPassword', - 'linkWith', - ], controller); + requireMethods( + 'UserController', + [ + 'setCurrentUser', + 'currentUser', + 'currentUserAsync', + 'signUp', + 'logIn', + 'become', + 'logOut', + 'me', + 'requestPasswordReset', + 'upgradeToRevocableSession', + 'requestEmailVerification', + 'verifyPassword', + 'linkWith', + ], + controller + ); config['UserController'] = controller; }, @@ -432,11 +453,11 @@ module.exports = { }, setLiveQueryController(controller: any) { - requireMethods('LiveQueryController', [ - 'setDefaultLiveQueryClient', - 'getDefaultLiveQueryClient', - '_clearCachedDefaultClient', - ], controller); + requireMethods( + 'LiveQueryController', + ['setDefaultLiveQueryClient', 'getDefaultLiveQueryClient', '_clearCachedDefaultClient'], + controller + ); config['LiveQueryController'] = controller; }, @@ -445,16 +466,11 @@ module.exports = { }, setHooksController(controller: HooksController) { - requireMethods('HooksController', [ - 'create', - 'get', - 'update', - 'remove', - ], controller); + requireMethods('HooksController', ['create', 'get', 'update', 'remove'], controller); config['HooksController'] = controller; }, getHooksController(): HooksController { return config['HooksController']; - } -} + }, +}; diff --git a/src/FacebookUtils.js b/src/FacebookUtils.js index 6c6d2a764..b8ec0fe27 100644 --- a/src/FacebookUtils.js +++ b/src/FacebookUtils.js @@ -19,24 +19,28 @@ const provider = { if (typeof FB === 'undefined') { options.error(this, 'Facebook SDK not found.'); } - FB.login((response) => { - if (response.authResponse) { - if (options.success) { - options.success(this, { - id: response.authResponse.userID, - access_token: response.authResponse.accessToken, - expiration_date: new Date(response.authResponse.expiresIn * 1000 + - (new Date()).getTime()).toJSON() - }); - } - } else { - if (options.error) { - options.error(this, response); + FB.login( + response => { + if (response.authResponse) { + if (options.success) { + options.success(this, { + id: response.authResponse.userID, + access_token: response.authResponse.accessToken, + expiration_date: new Date( + response.authResponse.expiresIn * 1000 + new Date().getTime() + ).toJSON(), + }); + } + } else { + if (options.error) { + options.error(this, response); + } } + }, + { + scope: requestedPermissions, } - }, { - scope: requestedPermissions - }); + ); }, restoreAuthentication(authData) { @@ -55,8 +59,7 @@ const provider = { // the FB SDK knows of a different user than the one being restored // from a Parse User that logged in with username/password. const existingResponse = FB.getAuthResponse(); - if (existingResponse && - existingResponse.userID !== authData.id) { + if (existingResponse && existingResponse.userID !== authData.id) { FB.logout(); } @@ -71,7 +74,7 @@ const provider = { deauthenticate() { this.restoreAuthentication(null); - } + }, }; /** @@ -102,9 +105,7 @@ const FacebookUtils = { */ init(options) { if (typeof FB === 'undefined') { - throw new Error( - 'The Facebook JavaScript SDK must be loaded before calling init.' - ); + throw new Error('The Facebook JavaScript SDK must be loaded before calling init.'); } initOptions = {}; if (options) { @@ -113,11 +114,14 @@ const FacebookUtils = { } } if (initOptions.status && typeof console !== 'undefined') { - const warn = console.warn || console.log || function() {}; // eslint-disable-line no-console - warn.call(console, 'The "status" flag passed into' + - ' FB.init, when set to true, can interfere with Parse Facebook' + - ' integration, so it has been suppressed. Please call' + - ' FB.getLoginStatus() explicitly if you require this behavior.'); + const warn = console.warn || console.log || function () {}; // eslint-disable-line no-console + warn.call( + console, + 'The "status" flag passed into' + + ' FB.init, when set to true, can interfere with Parse Facebook' + + ' integration, so it has been suppressed. Please call' + + ' FB.getLoginStatus() explicitly if you require this behavior.' + ); } initOptions.status = false; FB.init(initOptions); @@ -166,9 +170,7 @@ const FacebookUtils = { logIn(permissions, options) { if (!permissions || typeof permissions === 'string') { if (!initialized) { - throw new Error( - 'You must initialize FacebookUtils before calling logIn.' - ); + throw new Error('You must initialize FacebookUtils before calling logIn.'); } requestedPermissions = permissions; return ParseUser.logInWith('facebook', options); @@ -206,9 +208,7 @@ const FacebookUtils = { link(user, permissions, options) { if (!permissions || typeof permissions === 'string') { if (!initialized) { - throw new Error( - 'You must initialize FacebookUtils before calling link.' - ); + throw new Error('You must initialize FacebookUtils before calling link.'); } requestedPermissions = permissions; return user.linkWith('facebook', options); @@ -228,11 +228,9 @@ const FacebookUtils = { * callbacks. * @returns {Promise} */ - unlink: function(user, options) { + unlink: function (user, options) { if (!initialized) { - throw new Error( - 'You must initialize FacebookUtils before calling unlink.' - ); + throw new Error('You must initialize FacebookUtils before calling unlink.'); } return user._unlinkFrom('facebook', options); }, @@ -240,7 +238,7 @@ const FacebookUtils = { // Used for testing purposes _getAuthProvider() { return provider; - } + }, }; export default FacebookUtils; diff --git a/src/InstallationController.js b/src/InstallationController.js index 2611abe9f..c99697e4b 100644 --- a/src/InstallationController.js +++ b/src/InstallationController.js @@ -20,7 +20,7 @@ const InstallationController = { return Promise.resolve(iidCache); } const path = Storage.generatePath('installationId'); - return Storage.getItemAsync(path).then((iid) => { + return Storage.getItemAsync(path).then(iid => { if (!iid) { iid = uuidv4(); return Storage.setItemAsync(path, iid).then(() => { @@ -39,7 +39,7 @@ const InstallationController = { _setInstallationIdCache(iid: string) { iidCache = iid; - } + }, }; module.exports = InstallationController; diff --git a/src/LiveQueryClient.js b/src/LiveQueryClient.js index 108c2edca..e9a4391ae 100644 --- a/src/LiveQueryClient.js +++ b/src/LiveQueryClient.js @@ -22,7 +22,7 @@ const CLIENT_STATE = { CONNECTED: 'connected', CLOSED: 'closed', RECONNECTING: 'reconnecting', - DISCONNECTED: 'disconnected' + DISCONNECTED: 'disconnected', }; // The event type the LiveQuery client should sent to server @@ -30,7 +30,7 @@ const OP_TYPES = { CONNECT: 'connect', SUBSCRIBE: 'subscribe', UNSUBSCRIBE: 'unsubscribe', - ERROR: 'error' + ERROR: 'error', }; // The event we get back from LiveQuery server @@ -43,14 +43,14 @@ const OP_EVENTS = { UPDATE: 'update', ENTER: 'enter', LEAVE: 'leave', - DELETE: 'delete' + DELETE: 'delete', }; // The event the LiveQuery client should emit const CLIENT_EMMITER_TYPES = { CLOSE: 'close', ERROR: 'error', - OPEN: 'open' + OPEN: 'open', }; // The event the LiveQuery subscription should emit @@ -62,13 +62,12 @@ const SUBSCRIPTION_EMMITER_TYPES = { UPDATE: 'update', ENTER: 'enter', LEAVE: 'leave', - DELETE: 'delete' + DELETE: 'delete', }; - -const generateInterval = (k) => { - return Math.random() * Math.min(30, (Math.pow(2, k) - 1)) * 1000; -} +const generateInterval = k => { + return Math.random() * Math.min(30, Math.pow(2, k) - 1) * 1000; +}; /** * Creates a new LiveQueryClient. @@ -150,7 +149,9 @@ class LiveQueryClient extends EventEmitter { super(); if (!serverURL || serverURL.indexOf('ws') !== 0) { - throw new Error('You need to set a proper Parse LiveQuery server url before using LiveQueryClient'); + throw new Error( + 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' + ); } this.reconnectHandle = null; @@ -205,8 +206,8 @@ class LiveQueryClient extends EventEmitter { query: { className, where, - fields - } + fields, + }, }; if (sessionToken) { @@ -236,8 +237,8 @@ class LiveQueryClient extends EventEmitter { this.subscriptions.delete(subscription.id); const unsubscribeRequest = { op: OP_TYPES.UNSUBSCRIBE, - requestId: subscription.id - } + requestId: subscription.id, + }; this.connectPromise.then(() => { this.socket.send(JSON.stringify(unsubscribeRequest)); }); @@ -266,7 +267,7 @@ class LiveQueryClient extends EventEmitter { this._handleWebSocketOpen(); }; - this.socket.onmessage = (event) => { + this.socket.onmessage = event => { this._handleWebSocketMessage(event); }; @@ -274,7 +275,7 @@ class LiveQueryClient extends EventEmitter { this._handleWebSocketClose(); }; - this.socket.onerror = (error) => { + this.socket.onerror = error => { this._handleWebSocketError(error); }; } @@ -293,8 +294,8 @@ class LiveQueryClient extends EventEmitter { query: { className, where, - fields - } + fields, + }, }; if (sessionToken) { @@ -343,7 +344,7 @@ class LiveQueryClient extends EventEmitter { applicationId: this.applicationId, javascriptKey: this.javascriptKey, masterKey: this.masterKey, - sessionToken: this.sessionToken + sessionToken: this.sessionToken, }; if (this.additionalProperties) { connectRequest.installationId = this.installationId; @@ -358,14 +359,13 @@ class LiveQueryClient extends EventEmitter { } let subscription = null; if (data.requestId) { - subscription = - this.subscriptions.get(data.requestId); + subscription = this.subscriptions.get(data.requestId); } const response = { clientId: data.clientId, installationId: data.installationId, }; - switch(data.op) { + switch (data.op) { case OP_EVENTS.CONNECTED: if (this.state === CLIENT_STATE.RECONNECTING) { this.resubscribe(); @@ -474,18 +474,23 @@ class LiveQueryClient extends EventEmitter { clearTimeout(this.reconnectHandle); } - this.reconnectHandle = setTimeout((() => { - this.attempts++; - this.connectPromise = resolvingPromise(); - this.open(); - }).bind(this), time); + this.reconnectHandle = setTimeout( + (() => { + this.attempts++; + this.connectPromise = resolvingPromise(); + this.open(); + }).bind(this), + time + ); } } if (process.env.PARSE_BUILD === 'node') { CoreManager.setWebSocketController(require('ws')); } else if (process.env.PARSE_BUILD === 'browser') { - CoreManager.setWebSocketController(typeof WebSocket === 'function' || typeof WebSocket === 'object' ? WebSocket : null); + CoreManager.setWebSocketController( + typeof WebSocket === 'function' || typeof WebSocket === 'object' ? WebSocket : null + ); } else if (process.env.PARSE_BUILD === 'weapp') { CoreManager.setWebSocketController(require('./Socket.weapp')); } else if (process.env.PARSE_BUILD === 'react-native') { diff --git a/src/LiveQuerySubscription.js b/src/LiveQuerySubscription.js index 197143a80..0c5cf1b3d 100644 --- a/src/LiveQuerySubscription.js +++ b/src/LiveQuerySubscription.js @@ -122,10 +122,12 @@ class Subscription extends EventEmitter { * @returns {Promise} */ unsubscribe(): Promise { - return CoreManager.getLiveQueryController().getDefaultLiveQueryClient().then((liveQueryClient) => { - liveQueryClient.unsubscribe(this); - this.emit('close'); - }); + return CoreManager.getLiveQueryController() + .getDefaultLiveQueryClient() + .then(liveQueryClient => { + liveQueryClient.unsubscribe(this); + this.emit('close'); + }); } } diff --git a/src/LocalDatastore.js b/src/LocalDatastore.js index 187ece80c..7250c0375 100644 --- a/src/LocalDatastore.js +++ b/src/LocalDatastore.js @@ -186,7 +186,7 @@ const LocalDatastore = { if (!Array.isArray(pinned)) { return []; } - const promises = pinned.map((objectKey) => this.fromPinWithName(objectKey)); + const promises = pinned.map(objectKey => this.fromPinWithName(objectKey)); let objects = await Promise.all(promises); objects = [].concat(...objects); return objects.filter(object => object != null); @@ -211,7 +211,7 @@ const LocalDatastore = { meta[uniqueId] = root; queue.push(uniqueId); - while(queue.length !== 0) { + while (queue.length !== 0) { const nodeId = queue.shift(); const subTreeRoot = meta[nodeId]; for (const field in subTreeRoot) { @@ -258,9 +258,7 @@ const LocalDatastore = { if (!pin) { return; } - const promises = [ - this.unPinWithName(objectKey) - ]; + const promises = [this.unPinWithName(objectKey)]; delete localDatastore[objectKey]; for (const key in localDatastore) { @@ -293,10 +291,7 @@ const LocalDatastore = { if (!unsaved || unsaved.length === 0) { return; } - const promises = [ - this.unPinWithName(localKey), - this.pinWithName(objectKey, unsaved), - ]; + const promises = [this.unPinWithName(localKey), this.pinWithName(objectKey, unsaved)]; const localDatastore = await this._getAllContents(); for (const key in localDatastore) { @@ -342,7 +337,7 @@ const LocalDatastore = { const pointersHash = {}; for (const key of keys) { // Ignore the OBJECT_PREFIX - let [ , , className, objectId] = key.split('_'); + let [, , className, objectId] = key.split('_'); // User key is split into [ 'Parse', 'LDS', '', 'User', 'objectId' ] if (key.split('_').length === 5 && key.split('_')[3] === 'User') { @@ -371,13 +366,13 @@ const LocalDatastore = { try { const responses = await Promise.all(queryPromises); const objects = [].concat.apply([], responses); - const pinPromises = objects.map((object) => { + const pinPromises = objects.map(object => { const objectKey = this.getKeyForObject(object); return this.pinWithName(objectKey, object._toFullJSON()); }); await Promise.all(pinPromises); this.isSyncing = false; - } catch(error) { + } catch (error) { console.error('Error syncing LocalDatastore: ', error); this.isSyncing = false; } @@ -400,7 +395,7 @@ const LocalDatastore = { console.error('Parse.enableLocalDatastore() must be called first'); } return this.isEnabled; - } + }, }; module.exports = LocalDatastore; diff --git a/src/LocalDatastoreController.js b/src/LocalDatastoreController.js index ca0a5216f..dd8b6dffe 100644 --- a/src/LocalDatastoreController.js +++ b/src/LocalDatastoreController.js @@ -61,14 +61,14 @@ const LocalDatastoreController = { const keys = await Storage.getAllKeysAsync(); const toRemove = []; - for(const key of keys){ + for (const key of keys) { if (isLocalDatastoreKey(key)) { toRemove.push(key); } } const promises = toRemove.map(this.unPinWithName); return Promise.all(promises); - } + }, }; module.exports = LocalDatastoreController; diff --git a/src/LocalDatastoreController.react-native.js b/src/LocalDatastoreController.react-native.js index 0b26a2f86..6b6a77135 100644 --- a/src/LocalDatastoreController.react-native.js +++ b/src/LocalDatastoreController.react-native.js @@ -54,7 +54,7 @@ const LocalDatastoreController = { console.error('Error getAllContents: ', error); return {}; } - results.forEach((pair) => { + results.forEach(pair => { const [key, value] = pair; try { LDS[key] = JSON.parse(value); @@ -70,7 +70,7 @@ const LocalDatastoreController = { const keys = await RNStorage.getAllKeysAsync(); const storage = {}; const results = await RNStorage.multiGet(keys); - results.map((pair) => { + results.map(pair => { const [key, value] = pair; storage[key] = value; }); @@ -86,8 +86,10 @@ const LocalDatastoreController = { batch.push(key); } } - return RNStorage.multiRemove(batch).catch(error => console.error('Error clearing local datastore: ', error)); - } + return RNStorage.multiRemove(batch).catch(error => + console.error('Error clearing local datastore: ', error) + ); + }, }; module.exports = LocalDatastoreController; diff --git a/src/LocalDatastoreUtils.js b/src/LocalDatastoreUtils.js index de59e5ffc..d6922284f 100644 --- a/src/LocalDatastoreUtils.js +++ b/src/LocalDatastoreUtils.js @@ -15,12 +15,10 @@ const PIN_PREFIX = 'parsePin_'; const OBJECT_PREFIX = 'Parse_LDS_'; function isLocalDatastoreKey(key: string): boolean { - return !!(key && (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX) || key.startsWith(OBJECT_PREFIX))); + return !!( + key && + (key === DEFAULT_PIN || key.startsWith(PIN_PREFIX) || key.startsWith(OBJECT_PREFIX)) + ); } -export { - DEFAULT_PIN, - PIN_PREFIX, - OBJECT_PREFIX, - isLocalDatastoreKey, -}; +export { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX, isLocalDatastoreKey }; diff --git a/src/ObjectStateMutations.js b/src/ObjectStateMutations.js index a921b67df..f9911847e 100644 --- a/src/ObjectStateMutations.js +++ b/src/ObjectStateMutations.js @@ -23,11 +23,11 @@ export type OpsMap = { [attr: string]: Op }; export type ObjectCache = { [attr: string]: string }; export type State = { - serverData: AttributeMap; - pendingOps: Array; - objectCache: ObjectCache; - tasks: TaskQueue; - existed: boolean + serverData: AttributeMap, + pendingOps: Array, + objectCache: ObjectCache, + tasks: TaskQueue, + existed: boolean, }; export function defaultState(): State { @@ -36,7 +36,7 @@ export function defaultState(): State { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }; } @@ -86,17 +86,19 @@ export function mergeFirstPendingState(pendingOps: Array) { } } -export function estimateAttribute(serverData: AttributeMap, pendingOps: Array, className: string, id: ?string, attr: string): mixed { +export function estimateAttribute( + serverData: AttributeMap, + pendingOps: Array, + className: string, + id: ?string, + attr: string +): mixed { let value = serverData[attr]; for (let i = 0; i < pendingOps.length; i++) { if (pendingOps[i][attr]) { if (pendingOps[i][attr] instanceof RelationOp) { if (id) { - value = pendingOps[i][attr].applyTo( - value, - { className: className, id: id }, - attr - ); + value = pendingOps[i][attr].applyTo(value, { className: className, id: id }, attr); } } else { value = pendingOps[i][attr].applyTo(value); @@ -106,7 +108,12 @@ export function estimateAttribute(serverData: AttributeMap, pendingOps: Array, className: string, id: ?string): AttributeMap { +export function estimateAttributes( + serverData: AttributeMap, + pendingOps: Array, + className: string, + id: ?string +): AttributeMap { const data = {}; let attr; for (attr in serverData) { @@ -143,11 +150,16 @@ export function estimateAttributes(serverData: AttributeMap, pendingOps: Array -1) { - expString += compareTo.substring(escapeStart + 2, escapeEnd).replace(/\\\\\\\\E/g, '\\E').replace(/\W/g, '\\$&'); + expString += compareTo + .substring(escapeStart + 2, escapeEnd) + .replace(/\\\\\\\\E/g, '\\E') + .replace(/\W/g, '\\$&'); } escapeStart = compareTo.indexOf('\\Q', escapeEnd); } expString += compareTo.substring(Math.max(escapeStart, escapeEnd + 2)); let modifiers = constraints.$options || ''; - modifiers = modifiers.replace('x', '').replace('s', '') + modifiers = modifiers.replace('x', '').replace('s', ''); // Parse Server / Mongo support x and s modifiers but JS RegExp doesn't const exp = new RegExp(expString, modifiers); if (!exp.test(object[key])) { @@ -266,7 +280,12 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { // Invalid box, crosses the date line return false; } - return object[key].latitude > southWest.latitude && object[key].latitude < northEast.latitude && object[key].longitude > southWest.longitude && object[key].longitude < northEast.longitude; + return ( + object[key].latitude > southWest.latitude && + object[key].latitude < northEast.latitude && + object[key].longitude > southWest.longitude && + object[key].longitude < northEast.longitude + ); } case '$options': // Not a query type, but a way to add options to $regex. Ignore and @@ -303,8 +322,10 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); - if (object[key].className === subObject.className && - object[key].objectId === subObject.objectId) { + if ( + object[key].className === subObject.className && + object[key].objectId === subObject.objectId + ) { return true; } } @@ -317,8 +338,10 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { for (let i = 0; i < subQueryObjects.length; i += 1) { const subObject = transformObject(subQueryObjects[i]); - if (object[key].className === subObject.className && - object[key].objectId === subObject.objectId) { + if ( + object[key].className === subObject.className && + object[key].objectId === subObject.objectId + ) { return false; } } @@ -333,7 +356,7 @@ function matchesKeyConstraints(className, object, objects, key, constraints) { return true; } case '$geoWithin': { - const points = compareTo.$polygon.map((geoPoint) => [geoPoint.latitude, geoPoint.longitude]); + const points = compareTo.$polygon.map(geoPoint => [geoPoint.latitude, geoPoint.longitude]); const polygon = new ParsePolygon(points); return polygon.containsPoint(object[key]); } @@ -355,13 +378,27 @@ function validateQuery(query: any) { if (query.toJSON) { q = query.toJSON().where; } - const specialQuerykeys = ['$and', '$or', '$nor', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count']; + const specialQuerykeys = [ + '$and', + '$or', + '$nor', + '_rperm', + '_wperm', + '_perishable_token', + '_email_verify_token', + '_email_verify_token_expires_at', + '_account_lockout_expires_at', + '_failed_login_count', + ]; Object.keys(q).forEach(key => { if (q && q[key] && q[key].$regex) { if (typeof q[key].$options === 'string') { if (!q[key].$options.match(/^[imxs]+$/)) { - throw new ParseError(ParseError.INVALID_QUERY, `Bad $options value for query: ${q[key].$options}`); + throw new ParseError( + ParseError.INVALID_QUERY, + `Bad $options value for query: ${q[key].$options}` + ); } } } diff --git a/src/Parse.js b/src/Parse.js index 7fd2db52e..a627da859 100644 --- a/src/Parse.js +++ b/src/Parse.js @@ -33,11 +33,15 @@ const Parse = { * @static */ initialize(applicationId: string, javaScriptKey: string) { - if (process.env.PARSE_BUILD === 'browser' && CoreManager.get('IS_NODE') && !process.env.SERVER_RENDERING) { + if ( + process.env.PARSE_BUILD === 'browser' && + CoreManager.get('IS_NODE') && + !process.env.SERVER_RENDERING + ) { /* eslint-disable no-console */ console.log( - 'It looks like you\'re using the browser version of the SDK in a ' + - 'node.js environment. You should require(\'parse/node\') instead.' + "It looks like you're using the browser version of the SDK in a " + + "node.js environment. You should require('parse/node') instead." ); /* eslint-enable no-console */ } @@ -206,7 +210,7 @@ Parse.Op = { Add: ParseOp.AddOp, Remove: ParseOp.RemoveOp, AddUnique: ParseOp.AddUniqueOp, - Relation: ParseOp.RelationOp + Relation: ParseOp.RelationOp, }; Parse.Push = require('./Push'); Parse.Query = require('./ParseQuery').default; @@ -219,40 +223,40 @@ Parse.User = require('./ParseUser').default; Parse.LiveQuery = require('./ParseLiveQuery').default; Parse.LiveQueryClient = require('./LiveQueryClient').default; -Parse._request = function(...args) { +Parse._request = function (...args) { return CoreManager.getRESTController().request.apply(null, args); }; -Parse._ajax = function(...args) { +Parse._ajax = function (...args) { return CoreManager.getRESTController().ajax.apply(null, args); }; // We attempt to match the signatures of the legacy versions of these methods -Parse._decode = function(_, value) { +Parse._decode = function (_, value) { return decode(value); -} -Parse._encode = function(value, _, disallowObjects) { +}; +Parse._encode = function (value, _, disallowObjects) { return encode(value, disallowObjects); -} -Parse._getInstallationId = function() { +}; +Parse._getInstallationId = function () { return CoreManager.getInstallationController().currentInstallationId(); -} +}; /** * Enable pinning in your application. * This must be called before your application can use pinning. * * @static */ -Parse.enableLocalDatastore = function() { +Parse.enableLocalDatastore = function () { Parse.LocalDatastore.isEnabled = true; -} +}; /** * Flag that indicates whether Local Datastore is enabled. * * @static * @returns {boolean} */ -Parse.isLocalDatastoreEnabled = function() { +Parse.isLocalDatastoreEnabled = function () { return Parse.LocalDatastore.isEnabled; -} +}; /** * Gets all contents from Local Datastore * @@ -263,14 +267,14 @@ Parse.isLocalDatastoreEnabled = function() { * @static * @returns {object} */ -Parse.dumpLocalDatastore = function() { +Parse.dumpLocalDatastore = function () { if (!Parse.LocalDatastore.isEnabled) { console.log('Parse.enableLocalDatastore() must be called first'); // eslint-disable-line no-console return Promise.resolve({}); } else { return Parse.LocalDatastore._getAllContents(); } -} +}; /** * Enable the current user encryption. @@ -278,9 +282,9 @@ Parse.dumpLocalDatastore = function() { * * @static */ -Parse.enableEncryptedUser = function() { +Parse.enableEncryptedUser = function () { Parse.encryptedUser = true; -} +}; /** * Flag that indicates whether Encrypted User is enabled. @@ -288,9 +292,9 @@ Parse.enableEncryptedUser = function() { * @static * @returns {boolean} */ -Parse.isEncryptedUserEnabled = function() { +Parse.isEncryptedUserEnabled = function () { return Parse.encryptedUser; -} +}; CoreManager.setCryptoController(CryptoController); CoreManager.setInstallationController(InstallationController); @@ -299,9 +303,9 @@ CoreManager.setRESTController(RESTController); if (process.env.PARSE_BUILD === 'node') { Parse.initialize = Parse._initialize; Parse.Cloud = Parse.Cloud || {}; - Parse.Cloud.useMasterKey = function() { + Parse.Cloud.useMasterKey = function () { CoreManager.set('USE_MASTER_KEY', true); - } + }; Parse.Hooks = require('./ParseHooks'); } diff --git a/src/ParseACL.js b/src/ParseACL.js index c756fec25..398f6607f 100644 --- a/src/ParseACL.js +++ b/src/ParseACL.js @@ -50,23 +50,17 @@ class ParseACL { for (const permission in accessList) { const allowed = accessList[permission]; if (permission !== 'read' && permission !== 'write') { - throw new TypeError( - 'Tried to create an ACL with an invalid permission type.' - ); + throw new TypeError('Tried to create an ACL with an invalid permission type.'); } if (typeof allowed !== 'boolean') { - throw new TypeError( - 'Tried to create an ACL with an invalid permission value.' - ); + throw new TypeError('Tried to create an ACL with an invalid permission value.'); } this.permissionsById[userId][permission] = allowed; } } } } else if (typeof arg1 === 'function') { - throw new TypeError( - 'ParseACL constructed with a function. Did you forget ()?' - ); + throw new TypeError('ParseACL constructed with a function. Did you forget ()?'); } } @@ -149,10 +143,7 @@ class ParseACL { } } - _getAccess( - accessType: string, - userId: ParseUser | ParseRole | string - ): boolean { + _getAccess(accessType: string, userId: ParseUser | ParseRole | string): boolean { if (userId instanceof ParseUser) { userId = userId.id; if (!userId) { @@ -269,9 +260,7 @@ class ParseACL { role = role.getName(); } if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + throw new TypeError('role must be a ParseRole or a String'); } return this.getReadAccess('role:' + role); } @@ -291,9 +280,7 @@ class ParseACL { role = role.getName(); } if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + throw new TypeError('role must be a ParseRole or a String'); } return this.getWriteAccess('role:' + role); } @@ -312,9 +299,7 @@ class ParseACL { role = role.getName(); } if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + throw new TypeError('role must be a ParseRole or a String'); } this.setReadAccess('role:' + role, allowed); } @@ -333,9 +318,7 @@ class ParseACL { role = role.getName(); } if (typeof role !== 'string') { - throw new TypeError( - 'role must be a ParseRole or a String' - ); + throw new TypeError('role must be a ParseRole or a String'); } this.setWriteAccess('role:' + role, allowed); } diff --git a/src/ParseConfig.js b/src/ParseConfig.js index ebd11883b..de77a8097 100644 --- a/src/ParseConfig.js +++ b/src/ParseConfig.js @@ -110,11 +110,14 @@ class ParseConfig { static save(attrs: { [key: string]: any }, masterKeyOnlyFlags: { [key: string]: any }) { const controller = CoreManager.getConfigController(); //To avoid a mismatch with the local and the cloud config we get a new version - return controller.save(attrs, masterKeyOnlyFlags).then(() => { - return controller.get({ useMasterKey: true }); - },(error) => { - return Promise.reject(error); - }); + return controller.save(attrs, masterKeyOnlyFlags).then( + () => { + return controller.get({ useMasterKey: true }); + }, + error => { + return Promise.reject(error); + } + ); } /** @@ -137,7 +140,7 @@ function decodePayload(data) { if (json && typeof json === 'object') { return decode(json); } - } catch(e) { + } catch (e) { return null; } } @@ -163,7 +166,7 @@ const DefaultController = { return config; } // Return a promise for async storage controllers - return Storage.getItemAsync(storagePath).then((configData) => { + return Storage.getItemAsync(storagePath).then(configData => { if (configData) { const attributes = decodePayload(configData); if (attributes) { @@ -178,14 +181,9 @@ const DefaultController = { get(options: RequestOptions = {}) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'config', {}, options - ).then((response) => { + return RESTController.request('GET', 'config', {}, options).then(response => { if (!response || !response.params) { - const error = new ParseError( - ParseError.INVALID_JSON, - 'Config JSON response invalid.' - ); + const error = new ParseError(ParseError.INVALID_JSON, 'Config JSON response invalid.'); return Promise.reject(error); } @@ -207,8 +205,8 @@ const DefaultController = { save(attrs: { [key: string]: any }, masterKeyOnlyFlags: { [key: string]: any }) { const RESTController = CoreManager.getRESTController(); const encodedAttrs = {}; - for(const key in attrs){ - encodedAttrs[key] = encode(attrs[key]) + for (const key in attrs) { + encodedAttrs[key] = encode(attrs[key]); } return RESTController.request( 'PUT', @@ -216,17 +214,17 @@ const DefaultController = { { params: encodedAttrs, masterKeyOnly: masterKeyOnlyFlags }, { useMasterKey: true } ).then(response => { - if(response && response.result){ - return Promise.resolve() + if (response && response.result) { + return Promise.resolve(); } else { const error = new ParseError( ParseError.INTERNAL_SERVER_ERROR, 'Error occured updating Config.' ); - return Promise.reject(error) + return Promise.reject(error); } - }) - } + }); + }, }; CoreManager.setConfigController(DefaultController); diff --git a/src/ParseError.js b/src/ParseError.js index 4053e9df9..79d5358ff 100644 --- a/src/ParseError.js +++ b/src/ParseError.js @@ -22,7 +22,7 @@ class ParseError extends Error { this.code = code; Object.defineProperty(this, 'message', { enumerable: true, - value: message + value: message, }); } @@ -309,7 +309,7 @@ ParseError.SCRIPT_FAILED = 141; * @property {number} VALIDATION_ERROR * @static */ -ParseError.VALIDATION_ERROR = 142 +ParseError.VALIDATION_ERROR = 142; /** * Error code indicating that invalid image data was provided. diff --git a/src/ParseFile.js b/src/ParseFile.js index 2d377d302..d4ff9b520 100644 --- a/src/ParseFile.js +++ b/src/ParseFile.js @@ -25,22 +25,24 @@ if (process.env.PARSE_BUILD === 'weapp') { type Base64 = { base64: string }; type Uri = { uri: string }; type FileData = Array | Base64 | Blob | Uri; -export type FileSource = { - format: 'file'; - file: Blob; - type: string -} | { - format: 'base64'; - base64: string; - type: string -} | { - format: 'uri'; - uri: string; - type: string -}; +export type FileSource = + | { + format: 'file', + file: Blob, + type: string, + } + | { + format: 'base64', + base64: string, + type: string, + } + | { + format: 'uri', + uri: string, + type: string, + }; -const dataUriRegexp = - /^data:([a-zA-Z]+\/[-a-zA-Z0-9+.]+)(;charset=[a-zA-Z0-9\-\/]*)?;base64,/; +const dataUriRegexp = /^data:([a-zA-Z]+\/[-a-zA-Z0-9+.]+)(;charset=[a-zA-Z0-9\-\/]*)?;base64,/; function b64Digit(number: number): string { if (number < 26) { @@ -120,19 +122,19 @@ class ParseFile { this._source = { format: 'base64', base64: this._data, - type: specifiedType + type: specifiedType, }; } else if (typeof Blob !== 'undefined' && data instanceof Blob) { this._source = { format: 'file', file: data, - type: specifiedType + type: specifiedType, }; } else if (data && typeof data.uri === 'string' && data.uri !== undefined) { this._source = { format: 'uri', uri: data.uri, - type: specifiedType + type: specifiedType, }; } else if (data && typeof data.base64 === 'string') { const base64 = data.base64; @@ -145,14 +147,14 @@ class ParseFile { this._source = { format: 'base64', base64: this._data, - type: matches[1] + type: matches[1], }; } else { this._data = base64; this._source = { format: 'base64', base64: base64, - type: specifiedType + type: specifiedType, }; } } else { @@ -176,7 +178,7 @@ class ParseFile { throw new Error('Cannot retrieve data for unsaved ParseFile.'); } const options = { - requestTask: (task) => this._requestTask = task, + requestTask: task => (this._requestTask = task), }; const controller = CoreManager.getFileController(); const result = await controller.download(this._url, options); @@ -257,14 +259,14 @@ class ParseFile { */ save(options?: FullOptions) { options = options || {}; - options.requestTask = (task) => this._requestTask = task; + options.requestTask = task => (this._requestTask = task); options.metadata = this._metadata; options.tags = this._tags; const controller = CoreManager.getFileController(); if (!this._previousSave) { if (this._source.format === 'file') { - this._previousSave = controller.saveFile(this._name, this._source, options).then((res) => { + this._previousSave = controller.saveFile(this._name, this._source, options).then(res => { this._name = res.name; this._url = res.url; this._data = null; @@ -272,26 +274,29 @@ class ParseFile { return this; }); } else if (this._source.format === 'uri') { - this._previousSave = controller.download(this._source.uri, options).then((result) => { - if (!(result && result.base64)) { - return {}; - } - const newSource = { - format: 'base64', - base64: result.base64, - type: result.contentType, - }; - this._data = result.base64; - this._requestTask = null; - return controller.saveBase64(this._name, newSource, options); - }).then((res) => { - this._name = res.name; - this._url = res.url; - this._requestTask = null; - return this; - }); + this._previousSave = controller + .download(this._source.uri, options) + .then(result => { + if (!(result && result.base64)) { + return {}; + } + const newSource = { + format: 'base64', + base64: result.base64, + type: result.contentType, + }; + this._data = result.base64; + this._requestTask = null; + return controller.saveBase64(this._name, newSource, options); + }) + .then(res => { + this._name = res.name; + this._url = res.url; + this._requestTask = null; + return this; + }); } else { - this._previousSave = controller.saveBase64(this._name, this._source, options).then((res) => { + this._previousSave = controller.saveBase64(this._name, this._source, options).then(res => { this._name = res.name; this._url = res.url; this._requestTask = null; @@ -336,7 +341,7 @@ class ParseFile { return { __type: 'File', name: this._name, - url: this._url + url: this._url, }; } @@ -346,7 +351,7 @@ class ParseFile { } // Unsaved Files are never equal, since they will be saved to different URLs return ( - (other instanceof ParseFile) && + other instanceof ParseFile && this.name() === other.name() && this.url() === other.url() && typeof this.url() !== 'undefined' @@ -360,7 +365,7 @@ class ParseFile { */ setMetadata(metadata: any) { if (metadata && typeof metadata === 'object') { - Object.keys(metadata).forEach((key) => { + Object.keys(metadata).forEach(key => { this.addMetadata(key, metadata[key]); }); } @@ -385,7 +390,7 @@ class ParseFile { */ setTags(tags: any) { if (tags && typeof tags === 'object') { - Object.keys(tags).forEach((key) => { + Object.keys(tags).forEach(key => { this.addTag(key, tags[key]); }); } @@ -420,14 +425,14 @@ class ParseFile { const b2 = bytes[i * 3 + 1] || 0; const b3 = bytes[i * 3 + 2] || 0; - const has2 = (i * 3 + 1) < bytes.length; - const has3 = (i * 3 + 2) < bytes.length; + const has2 = i * 3 + 1 < bytes.length; + const has3 = i * 3 + 2 < bytes.length; chunks[i] = [ - b64Digit((b1 >> 2) & 0x3F), - b64Digit(((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0F)), - has2 ? b64Digit(((b2 << 2) & 0x3C) | ((b3 >> 6) & 0x03)) : '=', - has3 ? b64Digit(b3 & 0x3F) : '=' + b64Digit((b1 >> 2) & 0x3f), + b64Digit(((b1 << 4) & 0x30) | ((b2 >> 4) & 0x0f)), + has2 ? b64Digit(((b2 << 2) & 0x3c) | ((b3 >> 6) & 0x03)) : '=', + has3 ? b64Digit(b3 & 0x3f) : '=', ].join(''); } @@ -436,7 +441,7 @@ class ParseFile { } const DefaultController = { - saveFile: async function(name: string, source: FileSource, options?: FullOptions) { + saveFile: async function (name: string, source: FileSource, options?: FullOptions) { if (source.format !== 'file') { throw new Error('saveFile can only be used with File-type sources.'); } @@ -461,11 +466,11 @@ const DefaultController = { return await DefaultController.saveBase64(name, newSource, options); }, - saveBase64: function(name: string, source: FileSource, options?: FullOptions) { + saveBase64: function (name: string, source: FileSource, options?: FullOptions) { if (source.format !== 'base64') { throw new Error('saveBase64 can only be used with Base64-type sources.'); } - const data: { base64: any; _ContentType?: any, fileData: Object } = { + const data: { base64: any, _ContentType?: any, fileData: Object } = { base64: source.base64, fileData: { metadata: { ...options.metadata }, @@ -481,18 +486,16 @@ const DefaultController = { return CoreManager.getRESTController().request('POST', path, data, options); }, - download: function(uri, options) { + download: function (uri, options) { if (XHR) { return this.downloadAjax(uri, options); } else if (process.env.PARSE_BUILD === 'node') { return new Promise((resolve, reject) => { - const client = uri.indexOf('https') === 0 - ? require('https') - : require('http'); - const req = client.get(uri, (resp) => { + const client = uri.indexOf('https') === 0 ? require('https') : require('http'); + const req = client.get(uri, resp => { resp.setEncoding('base64'); let base64 = ''; - resp.on('data', (data) => base64 += data); + resp.on('data', data => (base64 += data)); resp.on('end', () => { resolve({ base64, @@ -511,13 +514,15 @@ const DefaultController = { } }, - downloadAjax: function(uri, options) { + downloadAjax: function (uri, options) { return new Promise((resolve, reject) => { const xhr = new XHR(); xhr.open('GET', uri, true); xhr.responseType = 'arraybuffer'; - xhr.onerror = function(e) { reject(e); }; - xhr.onreadystatechange = function() { + xhr.onerror = function (e) { + reject(e); + }; + xhr.onreadystatechange = function () { if (xhr.readyState !== xhr.DONE) { return; } @@ -535,7 +540,7 @@ const DefaultController = { }); }, - deleteFile: function(name) { + deleteFile: function (name) { const headers = { 'X-Parse-Application-ID': CoreManager.get('APPLICATION_ID'), 'X-Parse-Master-Key': CoreManager.get('MASTER_KEY'), @@ -545,14 +550,16 @@ const DefaultController = { url += '/'; } url += 'files/' + name; - return CoreManager.getRESTController().ajax('DELETE', url, '', headers).catch(response => { - // TODO: return JSON object in server - if (!response || response === 'SyntaxError: Unexpected end of JSON input') { - return Promise.resolve(); - } else { - return CoreManager.getRESTController().handleError(response); - } - }); + return CoreManager.getRESTController() + .ajax('DELETE', url, '', headers) + .catch(response => { + // TODO: return JSON object in server + if (!response || response === 'SyntaxError: Unexpected end of JSON input') { + return Promise.resolve(); + } else { + return CoreManager.getRESTController().handleError(response); + } + }); }, _setXHR(xhr: any) { diff --git a/src/ParseGeoPoint.js b/src/ParseGeoPoint.js index 71cb1f99b..001dca8a1 100644 --- a/src/ParseGeoPoint.js +++ b/src/ParseGeoPoint.js @@ -42,9 +42,8 @@ class ParseGeoPoint { * @param {number} arg2 The longitude of the GeoPoint */ constructor( - arg1: Array | - { latitude: number; longitude: number } | - number, arg2?: number + arg1: Array | { latitude: number, longitude: number } | number, + arg2?: number ) { if (Array.isArray(arg1)) { ParseGeoPoint._validate(arg1[0], arg1[1]); @@ -101,18 +100,18 @@ class ParseGeoPoint { * * @returns {object} */ - toJSON(): { __type: string; latitude: number; longitude: number } { + toJSON(): { __type: string, latitude: number, longitude: number } { ParseGeoPoint._validate(this._latitude, this._longitude); return { __type: 'GeoPoint', latitude: this._latitude, - longitude: this._longitude + longitude: this._longitude, }; } equals(other: mixed): boolean { return ( - (other instanceof ParseGeoPoint) && + other instanceof ParseGeoPoint && this.latitude === other.latitude && this.longitude === other.longitude ); @@ -135,9 +134,9 @@ class ParseGeoPoint { const sinDeltaLatDiv2 = Math.sin(deltaLat / 2); const sinDeltaLongDiv2 = Math.sin(deltaLong / 2); // Square of half the straight line chord distance between both points. - let a = ((sinDeltaLatDiv2 * sinDeltaLatDiv2) + - (Math.cos(lat1rad) * Math.cos(lat2rad) * - sinDeltaLongDiv2 * sinDeltaLongDiv2)); + let a = + sinDeltaLatDiv2 * sinDeltaLatDiv2 + + Math.cos(lat1rad) * Math.cos(lat2rad) * sinDeltaLongDiv2 * sinDeltaLongDiv2; a = Math.min(1.0, a); return 2 * Math.asin(Math.sqrt(a)); } @@ -167,32 +166,24 @@ class ParseGeoPoint { */ static _validate(latitude: number, longitude: number) { if ( - isNaN(latitude) || isNaN(longitude) || - typeof latitude !== 'number' || typeof longitude !== 'number' + isNaN(latitude) || + isNaN(longitude) || + typeof latitude !== 'number' || + typeof longitude !== 'number' ) { - throw new TypeError( - 'GeoPoint latitude and longitude must be valid numbers' - ); + throw new TypeError('GeoPoint latitude and longitude must be valid numbers'); } if (latitude < -90.0) { - throw new TypeError( - 'GeoPoint latitude out of bounds: ' + latitude + ' < -90.0.' - ); + throw new TypeError('GeoPoint latitude out of bounds: ' + latitude + ' < -90.0.'); } if (latitude > 90.0) { - throw new TypeError( - 'GeoPoint latitude out of bounds: ' + latitude + ' > 90.0.' - ); + throw new TypeError('GeoPoint latitude out of bounds: ' + latitude + ' > 90.0.'); } if (longitude < -180.0) { - throw new TypeError( - 'GeoPoint longitude out of bounds: ' + longitude + ' < -180.0.' - ); + throw new TypeError('GeoPoint longitude out of bounds: ' + longitude + ' < -180.0.'); } if (longitude > 180.0) { - throw new TypeError( - 'GeoPoint longitude out of bounds: ' + longitude + ' > 180.0.' - ); + throw new TypeError('GeoPoint longitude out of bounds: ' + longitude + ' > 180.0.'); } } @@ -203,7 +194,7 @@ class ParseGeoPoint { * @returns {Parse.GeoPoint} User's current location */ static current() { - return navigator.geolocation.getCurrentPosition((location) => { + return navigator.geolocation.getCurrentPosition(location => { return new ParseGeoPoint(location.coords.latitude, location.coords.longitude); }); } diff --git a/src/ParseHooks.js b/src/ParseHooks.js index 9637261de..8a5982687 100644 --- a/src/ParseHooks.js +++ b/src/ParseHooks.js @@ -3,27 +3,27 @@ import decode from './decode'; import ParseError from './ParseError'; export function getFunctions() { - return CoreManager.getHooksController().get("functions"); + return CoreManager.getHooksController().get('functions'); } -export function getTriggers() { - return CoreManager.getHooksController().get("triggers"); +export function getTriggers() { + return CoreManager.getHooksController().get('triggers'); } export function getFunction(name) { - return CoreManager.getHooksController().get("functions", name); + return CoreManager.getHooksController().get('functions', name); } export function getTrigger(className, triggerName) { - return CoreManager.getHooksController().get("triggers", className, triggerName); + return CoreManager.getHooksController().get('triggers', className, triggerName); } export function createFunction(functionName, url) { - return create({functionName: functionName, url: url}); + return create({ functionName: functionName, url: url }); } export function createTrigger(className, triggerName, url) { - return create({className: className, triggerName: triggerName, url: url}); + return create({ className: className, triggerName: triggerName, url: url }); } export function create(hook) { @@ -31,11 +31,11 @@ export function create(hook) { } export function updateFunction(functionName, url) { - return update({functionName: functionName, url: url}); + return update({ functionName: functionName, url: url }); } export function updateTrigger(className, triggerName, url) { - return update({className: className, triggerName: triggerName, url: url}); + return update({ className: className, triggerName: triggerName, url: url }); } export function update(hook) { @@ -43,11 +43,11 @@ export function update(hook) { } export function removeFunction(functionName) { - return remove({functionName: functionName}); + return remove({ functionName: functionName }); } export function removeTrigger(className, triggerName) { - return remove({className: className, triggerName: triggerName}); + return remove({ className: className, triggerName: triggerName }); } export function remove(hook) { @@ -55,74 +55,72 @@ export function remove(hook) { } const DefaultController = { - get(type, functionName, triggerName) { - let url = "/hooks/" + type; - if(functionName) { - url += "/" + functionName; + let url = '/hooks/' + type; + if (functionName) { + url += '/' + functionName; if (triggerName) { - url += "/" + triggerName; + url += '/' + triggerName; } } - return this.sendRequest("GET", url); + return this.sendRequest('GET', url); }, create(hook) { let url; if (hook.functionName && hook.url) { - url = "/hooks/functions"; + url = '/hooks/functions'; } else if (hook.className && hook.triggerName && hook.url) { - url = "/hooks/triggers"; + url = '/hooks/triggers'; } else { - return Promise.reject({error: 'invalid hook declaration', code: 143}); + return Promise.reject({ error: 'invalid hook declaration', code: 143 }); } - return this.sendRequest("POST", url, hook); + return this.sendRequest('POST', url, hook); }, remove(hook) { let url; if (hook.functionName) { - url = "/hooks/functions/" + hook.functionName; + url = '/hooks/functions/' + hook.functionName; delete hook.functionName; } else if (hook.className && hook.triggerName) { - url = "/hooks/triggers/" + hook.className + "/" + hook.triggerName; + url = '/hooks/triggers/' + hook.className + '/' + hook.triggerName; delete hook.className; delete hook.triggerName; } else { - return Promise.reject({error: 'invalid hook declaration', code: 143}); + return Promise.reject({ error: 'invalid hook declaration', code: 143 }); } - return this.sendRequest("PUT", url, { "__op": "Delete" }); + return this.sendRequest('PUT', url, { __op: 'Delete' }); }, update(hook) { let url; if (hook.functionName && hook.url) { - url = "/hooks/functions/" + hook.functionName; + url = '/hooks/functions/' + hook.functionName; delete hook.functionName; } else if (hook.className && hook.triggerName && hook.url) { - url = "/hooks/triggers/" + hook.className + "/" + hook.triggerName; + url = '/hooks/triggers/' + hook.className + '/' + hook.triggerName; delete hook.className; delete hook.triggerName; } else { - return Promise.reject({error: 'invalid hook declaration', code: 143}); + return Promise.reject({ error: 'invalid hook declaration', code: 143 }); } return this.sendRequest('PUT', url, hook); }, sendRequest(method, url, body) { - return CoreManager.getRESTController().request(method, url, body, {useMasterKey: true}).then((res) => { - const decoded = decode(res); - if (decoded) { - return Promise.resolve(decoded); - } - return Promise.reject( - new ParseError( - ParseError.INVALID_JSON, - 'The server returned an invalid response.' - ) - ); - }) - } + return CoreManager.getRESTController() + .request(method, url, body, { useMasterKey: true }) + .then(res => { + const decoded = decode(res); + if (decoded) { + return Promise.resolve(decoded); + } + return Promise.reject( + new ParseError(ParseError.INVALID_JSON, 'The server returned an invalid response.') + ); + }); + }, }; CoreManager.setHooksController(DefaultController); diff --git a/src/ParseInstallation.js b/src/ParseInstallation.js index a701faf2e..882214706 100644 --- a/src/ParseInstallation.js +++ b/src/ParseInstallation.js @@ -16,9 +16,9 @@ import type { AttributeMap } from './ObjectStateMutations'; export default class Installation extends ParseObject { constructor(attributes: ?AttributeMap) { super('_Installation'); - if (attributes && typeof attributes === 'object'){ + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { - throw new Error('Can\'t create an invalid Installation'); + throw new Error("Can't create an invalid Installation"); } } } diff --git a/src/ParseLiveQuery.js b/src/ParseLiveQuery.js index ee6a67624..d50dcff06 100644 --- a/src/ParseLiveQuery.js +++ b/src/ParseLiveQuery.js @@ -85,7 +85,7 @@ const DefaultLiveQueryController = { } const [currentUser, installationId] = await Promise.all([ CoreManager.getUserController().currentUserAsync(), - CoreManager.getInstallationController().currentInstallationId() + CoreManager.getInstallationController().currentInstallationId(), ]); const sessionToken = currentUser ? currentUser.getSessionToken() : undefined; @@ -117,7 +117,7 @@ const DefaultLiveQueryController = { sessionToken, installationId, }); - defaultLiveQueryClient.on('error', (error) => { + defaultLiveQueryClient.on('error', error => { LiveQuery.emit('error', error); }); defaultLiveQueryClient.on('open', () => { diff --git a/src/ParseObject.js b/src/ParseObject.js index 989fa81e7..1efb3101c 100644 --- a/src/ParseObject.js +++ b/src/ParseObject.js @@ -30,7 +30,7 @@ import { AddOp, AddUniqueOp, RemoveOp, - RelationOp + RelationOp, } from './ParseOp'; import ParseQuery from './ParseQuery'; import ParseRelation from './ParseRelation'; @@ -45,21 +45,21 @@ import type { RequestOptions, FullOptions } from './RESTController'; const uuidv4 = require('uuid/v4'); export type Pointer = { - __type: string; - className: string; - objectId: string; + __type: string, + className: string, + objectId: string, }; type SaveParams = { - method: string; - path: string; - body: AttributeMap; + method: string, + path: string, + body: AttributeMap, }; type SaveOptions = FullOptions & { - cascadeSave?: boolean; - context?: AttributeMap; -} + cascadeSave?: boolean, + context?: AttributeMap, +}; // Mapping of class names to constructors, so we can populate objects from the // server with appropriate subclasses of ParseObject @@ -70,7 +70,7 @@ let objectCount = 0; // On web clients, objects are single-instance: any two objects with the same Id // will have the same attributes. However, this may be dangerous default // behavior in a server scenario -let singleInstance = (!CoreManager.get('IS_NODE')); +let singleInstance = !CoreManager.get('IS_NODE'); if (singleInstance) { CoreManager.setObjectStateController(SingleInstanceStateController); } else { @@ -110,7 +110,11 @@ class ParseObject { * @param {object} attributes The initial set of data to store in the object. * @param {object} options The options for this object instance. */ - constructor(className: ?string | { className: string, [attr: string]: mixed }, attributes?: { [attr: string]: mixed }, options?: { ignoreValidation: boolean }) { + constructor( + className: ?string | { className: string, [attr: string]: mixed }, + attributes?: { [attr: string]: mixed }, + options?: { ignoreValidation: boolean } + ) { // Enable legacy initializers if (typeof this.initialize === 'function') { this.initialize.apply(this, arguments); @@ -136,7 +140,7 @@ class ParseObject { } } if (toSet && !this.set(toSet, options)) { - throw new Error('Can\'t create an invalid Parse Object'); + throw new Error("Can't create an invalid Parse Object"); } } @@ -201,7 +205,7 @@ class ParseObject { * * @returns {Parse.Object|object} */ - _getStateIdentifier(): ParseObject | {id: string, className: string} { + _getStateIdentifier(): ParseObject | { id: string, className: string } { if (singleInstance) { let id = this.id; if (!id) { @@ -209,7 +213,7 @@ class ParseObject { } return { id: id, - className: this.className + className: this.className, }; } else { return this; @@ -244,7 +248,7 @@ class ParseObject { const pending = this._getPendingOps(); const latest = pending[pending.length - 1]; const keys = keysToClear || Object.keys(latest); - keys.forEach((key) => { + keys.forEach(key => { delete latest[key]; }); } @@ -256,7 +260,8 @@ class ParseObject { const dirty = {}; for (const attr in attributes) { const val = attributes[attr]; - if (val && + if ( + val && typeof val === 'object' && !(val instanceof ParseObject) && !(val instanceof ParseFile) && @@ -329,7 +334,7 @@ class ParseObject { return { method, body, - path + path, }; } @@ -401,8 +406,7 @@ class ParseObject { } } for (attr in response) { - if ((attr === 'createdAt' || attr === 'updatedAt') && - typeof response[attr] === 'string') { + if ((attr === 'createdAt' || attr === 'updatedAt') && typeof response[attr] === 'string') { changes[attr] = parseDate(response[attr]); } else if (attr === 'ACL') { changes[attr] = new ParseACL(response[attr]); @@ -483,7 +487,7 @@ class ParseObject { return true; } return ( - (other instanceof ParseObject) && + other instanceof ParseObject && this.className === other.className && this.id === other.id && typeof this.id !== 'undefined' @@ -566,7 +570,7 @@ class ParseObject { return { __type: 'Pointer', className: this.className, - objectId: this.id + objectId: this.id, }; } @@ -582,7 +586,7 @@ class ParseObject { return { __type: 'Object', className: this.className, - _localId: this._localId + _localId: this._localId, }; } @@ -709,7 +713,8 @@ class ParseObject { newOps[k] = new UnsetOp(); } else if (changes[k] instanceof Op) { newOps[k] = changes[k]; - } else if (changes[k] && + } else if ( + changes[k] && typeof changes[k] === 'object' && typeof changes[k].__op === 'string' ) { @@ -1016,7 +1021,7 @@ class ParseObject { return false; } try { - const query = new ParseQuery(this.className) + const query = new ParseQuery(this.className); await query.get(this.id, options); return true; } catch (e) { @@ -1048,13 +1053,10 @@ class ParseObject { */ validate(attrs: AttributeMap): ParseError | boolean { if (attrs.hasOwnProperty('ACL') && !(attrs.ACL instanceof ParseACL)) { - return new ParseError( - ParseError.OTHER_CAUSE, - 'ACL must be a Parse ACL.' - ); + return new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.'); } for (const key in attrs) { - if (!(/^[A-Za-z][0-9A-Za-z_.]*$/).test(key)) { + if (!/^[A-Za-z][0-9A-Za-z_.]*$/.test(key)) { return new ParseError(ParseError.INVALID_KEY_NAME); } } @@ -1094,13 +1096,13 @@ class ParseObject { */ revert(...keys: Array): void { let keysToRevert; - if(keys.length) { + if (keys.length) { keysToRevert = []; - for(const key of keys) { - if(typeof(key) === "string") { + for (const key of keys) { + if (typeof key === 'string') { keysToRevert.push(key); } else { - throw new Error("Parse.Object#revert expects either no, or a list of string, arguments."); + throw new Error('Parse.Object#revert expects either no, or a list of string, arguments.'); } } } @@ -1159,7 +1161,7 @@ class ParseObject { if (options.hasOwnProperty('include')) { fetchOptions.include = []; if (Array.isArray(options.include)) { - options.include.forEach((key) => { + options.include.forEach(key => { if (Array.isArray(key)) { fetchOptions.include = fetchOptions.include.concat(key); } else { @@ -1192,7 +1194,7 @@ class ParseObject { * @returns {Promise} A promise that is fulfilled when the fetch * completes. */ - fetchWithInclude(keys: String|Array>, options: RequestOptions): Promise { + fetchWithInclude(keys: String | Array>, options: RequestOptions): Promise { options = options || {}; options.include = keys; return this.fetch(options); @@ -1332,10 +1334,7 @@ class ParseObject { if (!this.id) { return Promise.resolve(); } - return CoreManager.getObjectController().destroy( - this, - destroyOptions - ); + return CoreManager.getObjectController().destroy(this, destroyOptions); } /** @@ -1497,11 +1496,7 @@ class ParseObject { if (options.hasOwnProperty('include')) { queryOptions.include = ParseObject.handleIncludeOptions(options); } - return CoreManager.getObjectController().fetch( - list, - true, - queryOptions - ); + return CoreManager.getObjectController().fetch(list, true, queryOptions); } /** @@ -1533,7 +1528,11 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllWithInclude(list: Array, keys: String|Array>, options: RequestOptions) { + static fetchAllWithInclude( + list: Array, + keys: String | Array>, + options: RequestOptions + ) { options = options || {}; options.include = keys; return ParseObject.fetchAll(list, options); @@ -1569,7 +1568,11 @@ class ParseObject { * @static * @returns {Parse.Object[]} */ - static fetchAllIfNeededWithInclude(list: Array, keys: String|Array>, options: RequestOptions) { + static fetchAllIfNeededWithInclude( + list: Array, + keys: String | Array>, + options: RequestOptions + ) { options = options || {}; options.include = keys; return ParseObject.fetchAllIfNeeded(list, options); @@ -1606,17 +1609,13 @@ class ParseObject { if (options.hasOwnProperty('include')) { queryOptions.include = ParseObject.handleIncludeOptions(options); } - return CoreManager.getObjectController().fetch( - list, - false, - queryOptions - ); + return CoreManager.getObjectController().fetch(list, false, queryOptions); } static handleIncludeOptions(options) { let include = []; if (Array.isArray(options.include)) { - options.include.forEach((key) => { + options.include.forEach(key => { if (Array.isArray(key)) { include = include.concat(key); } else { @@ -1689,10 +1688,7 @@ class ParseObject { if (options.hasOwnProperty('context') && typeof options.context === 'object') { destroyOptions.context = options.context; } - return CoreManager.getObjectController().destroy( - list, - destroyOptions - ); + return CoreManager.getObjectController().destroy(list, destroyOptions); } /** @@ -1727,10 +1723,7 @@ class ParseObject { if (options.hasOwnProperty('context') && typeof options.context === 'object') { saveOptions.context = options.context; } - return CoreManager.getObjectController().save( - list, - saveOptions - ); + return CoreManager.getObjectController().save(list, saveOptions); } /** @@ -1814,7 +1807,7 @@ class ParseObject { if (typeof constructor !== 'function') { throw new TypeError( 'You must register the subclass constructor. ' + - 'Did you attempt to register an instance of the subclass?' + 'Did you attempt to register an instance of the subclass?' ); } classMap[className] = constructor; @@ -1865,9 +1858,7 @@ class ParseObject { if (className && typeof className.className === 'string') { return ParseObject.extend(className.className, className, protoProps); } else { - throw new Error( - 'Parse.Object.extend\'s first argument should be the className.' - ); + throw new Error("Parse.Object.extend's first argument should be the className."); } } let adjustedClassName = className; @@ -1882,7 +1873,7 @@ class ParseObject { } else if (classMap[adjustedClassName]) { parentProto = classMap[adjustedClassName].prototype; } - const ParseObjectSubclass = function(attributes, options) { + const ParseObjectSubclass = function (attributes, options) { this.className = adjustedClassName; this._objCount = objectCount++; // Enable legacy initializers @@ -1890,9 +1881,9 @@ class ParseObject { this.initialize.apply(this, arguments); } - if (attributes && typeof attributes === 'object'){ + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {}, options)) { - throw new Error('Can\'t create an invalid Parse Object'); + throw new Error("Can't create an invalid Parse Object"); } } }; @@ -1904,8 +1895,8 @@ class ParseObject { value: ParseObjectSubclass, enumerable: false, writable: true, - configurable: true - } + configurable: true, + }, }); if (protoProps) { @@ -1915,7 +1906,7 @@ class ParseObject { value: protoProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -1928,18 +1919,18 @@ class ParseObject { value: classProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } } - ParseObjectSubclass.extend = function(name, protoProps, classProps) { + ParseObjectSubclass.extend = function (name, protoProps, classProps) { if (typeof name === 'string') { return ParseObject.extend.call(ParseObjectSubclass, name, protoProps, classProps); } return ParseObject.extend.call(ParseObjectSubclass, adjustedClassName, name, protoProps); - } + }; ParseObjectSubclass.createWithoutData = ParseObject.createWithoutData; classMap[adjustedClassName] = ParseObjectSubclass; @@ -2104,7 +2095,11 @@ class ParseObject { } const DefaultController = { - fetch(target: ParseObject | Array, forceFetch: boolean, options: RequestOptions): Promise | ParseObject> { + fetch( + target: ParseObject | Array, + forceFetch: boolean, + options: RequestOptions + ): Promise | ParseObject> { const localDatastore = CoreManager.getLocalDatastore(); if (Array.isArray(target)) { if (target.length < 1) { @@ -2115,7 +2110,7 @@ const DefaultController = { let className = null; const results = []; let error = null; - target.forEach((el) => { + target.forEach(el => { if (error) { return; } @@ -2129,10 +2124,7 @@ const DefaultController = { ); } if (!el.id) { - error = new ParseError( - ParseError.MISSING_OBJECT_ID, - 'All objects must have an ID' - ); + error = new ParseError(ParseError.MISSING_OBJECT_ID, 'All objects must have an ID'); } if (forceFetch || !el.isDataAvailable()) { ids.push(el.id); @@ -2149,9 +2141,9 @@ const DefaultController = { query.include(options.include); } query._limit = ids.length; - return query.find(options).then(async (objects) => { + return query.find(options).then(async objects => { const idMap = {}; - objects.forEach((o) => { + objects.forEach(o => { idMap[o.id] = o; }); for (let i = 0; i < objs.length; i++) { @@ -2159,10 +2151,7 @@ const DefaultController = { if (!obj || !obj.id || !idMap[obj.id]) { if (forceFetch) { return Promise.reject( - new ParseError( - ParseError.OBJECT_NOT_FOUND, - 'All objects must exist on the server.' - ) + new ParseError(ParseError.OBJECT_NOT_FOUND, 'All objects must exist on the server.') ); } } @@ -2185,10 +2174,9 @@ const DefaultController = { }); } else if (target instanceof ParseObject) { if (!target.id) { - return Promise.reject(new ParseError( - ParseError.MISSING_OBJECT_ID, - 'Object does not have an ID' - )); + return Promise.reject( + new ParseError(ParseError.MISSING_OBJECT_ID, 'Object does not have an ID') + ); } const RESTController = CoreManager.getRESTController(); const params = {}; @@ -2200,7 +2188,7 @@ const DefaultController = { 'classes/' + target.className + '/' + target._getId(), params, options - ).then(async (response) => { + ).then(async response => { target._clearPendingOps(); target._clearServerData(); target._finishFetch(response); @@ -2211,8 +2199,12 @@ const DefaultController = { return Promise.resolve(); }, - async destroy(target: ParseObject | Array, options: RequestOptions): Promise | ParseObject> { - const batchSize = (options && options.batchSize) ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); + async destroy( + target: ParseObject | Array, + options: RequestOptions + ): Promise | ParseObject> { + const batchSize = + options && options.batchSize ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); const localDatastore = CoreManager.getLocalDatastore(); const RESTController = CoreManager.getRESTController(); @@ -2221,7 +2213,7 @@ const DefaultController = { return Promise.resolve([]); } const batches = [[]]; - target.forEach((obj) => { + target.forEach(obj => { if (!obj.id) { return; } @@ -2236,23 +2228,25 @@ const DefaultController = { } let deleteCompleted = Promise.resolve(); const errors = []; - batches.forEach((batch) => { + batches.forEach(batch => { deleteCompleted = deleteCompleted.then(() => { - return RESTController.request('POST', 'batch', { - requests: batch.map((obj) => { - return { - method: 'DELETE', - path: getServerUrlPath() + 'classes/' + obj.className + '/' + obj._getId(), - body: {} - }; - }) - }, options).then((results) => { + return RESTController.request( + 'POST', + 'batch', + { + requests: batch.map(obj => { + return { + method: 'DELETE', + path: getServerUrlPath() + 'classes/' + obj.className + '/' + obj._getId(), + body: {}, + }; + }), + }, + options + ).then(results => { for (let i = 0; i < results.length; i++) { if (results[i] && results[i].hasOwnProperty('error')) { - const err = new ParseError( - results[i].error.code, - results[i].error.error - ); + const err = new ParseError(results[i].error.code, results[i].error.error); err.object = batch[i]; errors.push(err); } @@ -2286,7 +2280,8 @@ const DefaultController = { }, save(target: ParseObject | Array, options: RequestOptions) { - const batchSize = (options && options.batchSize) ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); + const batchSize = + options && options.batchSize ? options.batchSize : CoreManager.get('REQUEST_BATCH_SIZE'); const localDatastore = CoreManager.getLocalDatastore(); const mapIdForPin = {}; @@ -2310,7 +2305,7 @@ const DefaultController = { const filesSaved: Array = []; let pending: Array = []; - unsaved.forEach((el) => { + unsaved.forEach(el => { if (el instanceof ParseFile) { filesSaved.push(el.save(options)); } else if (el instanceof ParseObject) { @@ -2320,75 +2315,82 @@ const DefaultController = { return Promise.all(filesSaved).then(() => { let objectError = null; - return continueWhile(() => { - return pending.length > 0; - }, () => { - const batch = []; - const nextPending = []; - pending.forEach((el) => { - if (batch.length < batchSize && canBeSerialized(el)) { - batch.push(el); - } else { - nextPending.push(el); + return continueWhile( + () => { + return pending.length > 0; + }, + () => { + const batch = []; + const nextPending = []; + pending.forEach(el => { + if (batch.length < batchSize && canBeSerialized(el)) { + batch.push(el); + } else { + nextPending.push(el); + } + }); + pending = nextPending; + if (batch.length < 1) { + return Promise.reject( + new ParseError(ParseError.OTHER_CAUSE, 'Tried to save a batch with a cycle.') + ); } - }); - pending = nextPending; - if (batch.length < 1) { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Tried to save a batch with a cycle.' - ) - ); - } - // Queue up tasks for each object in the batch. - // When every task is ready, the API request will execute - const batchReturned = new resolvingPromise(); - const batchReady = []; - const batchTasks = []; - batch.forEach((obj, index) => { - const ready = new resolvingPromise(); - batchReady.push(ready); - const task = function() { - ready.resolve(); - return batchReturned.then((responses) => { - if (responses[index].hasOwnProperty('success')) { - const objectId = responses[index].success.objectId; - const status = responses[index]._status; - delete responses[index]._status; - mapIdForPin[objectId] = obj._localId; - obj._handleSaveResponse(responses[index].success, status); - } else { - if (!objectError && responses[index].hasOwnProperty('error')) { - const serverError = responses[index].error; - objectError = new ParseError(serverError.code, serverError.error); - // Cancel the rest of the save - pending = []; + // Queue up tasks for each object in the batch. + // When every task is ready, the API request will execute + const batchReturned = new resolvingPromise(); + const batchReady = []; + const batchTasks = []; + batch.forEach((obj, index) => { + const ready = new resolvingPromise(); + batchReady.push(ready); + const task = function () { + ready.resolve(); + return batchReturned.then(responses => { + if (responses[index].hasOwnProperty('success')) { + const objectId = responses[index].success.objectId; + const status = responses[index]._status; + delete responses[index]._status; + mapIdForPin[objectId] = obj._localId; + obj._handleSaveResponse(responses[index].success, status); + } else { + if (!objectError && responses[index].hasOwnProperty('error')) { + const serverError = responses[index].error; + objectError = new ParseError(serverError.code, serverError.error); + // Cancel the rest of the save + pending = []; + } + obj._handleSaveError(); } - obj._handleSaveError(); - } - }); - }; - stateController.pushPendingState(obj._getStateIdentifier()); - batchTasks.push(stateController.enqueueTask(obj._getStateIdentifier(), task)); - }); - - when(batchReady).then(() => { - // Kick off the batch request - return RESTController.request('POST', 'batch', { - requests: batch.map((obj) => { - const params = obj._getSaveParams(); - params.path = getServerUrlPath() + params.path; - return params; + }); + }; + stateController.pushPendingState(obj._getStateIdentifier()); + batchTasks.push(stateController.enqueueTask(obj._getStateIdentifier(), task)); + }); + + when(batchReady) + .then(() => { + // Kick off the batch request + return RESTController.request( + 'POST', + 'batch', + { + requests: batch.map(obj => { + const params = obj._getSaveParams(); + params.path = getServerUrlPath() + params.path; + return params; + }), + }, + options + ); }) - }, options); - }).then(batchReturned.resolve, (error) => { - batchReturned.reject(new ParseError(ParseError.INCORRECT_TYPE, error.message)); - }); + .then(batchReturned.resolve, error => { + batchReturned.reject(new ParseError(ParseError.INCORRECT_TYPE, error.message)); + }); - return when(batchTasks); - }).then(async () => { + return when(batchTasks); + } + ).then(async () => { if (objectError) { return Promise.reject(objectError); } @@ -2399,42 +2401,42 @@ const DefaultController = { return Promise.resolve(target); }); }); - } else if (target instanceof ParseObject) { // generate _localId in case if cascadeSave=false target._getId(); const localId = target._localId; // copying target lets Flow guarantee the pointer isn't modified elsewhere const targetCopy = target; - const task = function() { + const task = function () { const params = targetCopy._getSaveParams(); - return RESTController.request( - params.method, - params.path, - params.body, - options - ).then((response) => { - const status = response._status; - delete response._status; - targetCopy._handleSaveResponse(response, status); - }, (error) => { - targetCopy._handleSaveError(); - return Promise.reject(error); - }); - } + return RESTController.request(params.method, params.path, params.body, options).then( + response => { + const status = response._status; + delete response._status; + targetCopy._handleSaveResponse(response, status); + }, + error => { + targetCopy._handleSaveError(); + return Promise.reject(error); + } + ); + }; stateController.pushPendingState(target._getStateIdentifier()); - return stateController.enqueueTask(target._getStateIdentifier(), task).then(async () => { - await localDatastore._updateLocalIdForObject(localId, target); - await localDatastore._updateObjectIfPinned(target); - return target; - }, (error) => { - return Promise.reject(error); - }); + return stateController.enqueueTask(target._getStateIdentifier(), task).then( + async () => { + await localDatastore._updateLocalIdForObject(localId, target); + await localDatastore._updateObjectIfPinned(target); + return target; + }, + error => { + return Promise.reject(error); + } + ); } return Promise.resolve(); - } -} + }, +}; CoreManager.setObjectController(DefaultController); diff --git a/src/ParseOp.js b/src/ParseOp.js index 8b5ba7d24..0029916e7 100644 --- a/src/ParseOp.js +++ b/src/ParseOp.js @@ -109,9 +109,7 @@ export class IncrementOp extends Op { constructor(amount: number) { super(); if (typeof amount !== 'number') { - throw new TypeError( - 'Increment Op must be initialized with a numeric amount.' - ); + throw new TypeError('Increment Op must be initialized with a numeric amount.'); } this._amount = amount; } @@ -142,7 +140,7 @@ export class IncrementOp extends Op { throw new Error('Cannot merge Increment Op with the previous Op'); } - toJSON(): { __op: string; amount: number } { + toJSON(): { __op: string, amount: number } { return { __op: 'Increment', amount: this._amount }; } } @@ -152,7 +150,7 @@ export class AddOp extends Op { constructor(value: mixed | Array) { super(); - this._value = (Array.isArray(value) ? value : [value]); + this._value = Array.isArray(value) ? value : [value]; } applyTo(value: mixed): Array { @@ -181,7 +179,7 @@ export class AddOp extends Op { throw new Error('Cannot merge Add Op with the previous Op'); } - toJSON(): { __op: string; objects: mixed } { + toJSON(): { __op: string, objects: mixed } { return { __op: 'Add', objects: encode(this._value, false, true) }; } } @@ -200,7 +198,7 @@ export class AddUniqueOp extends Op { } if (Array.isArray(value)) { const toAdd = []; - this._value.forEach((v) => { + this._value.forEach(v => { if (v instanceof ParseObject) { if (!arrayContainsObject(value, v)) { toAdd.push(v); @@ -210,7 +208,7 @@ export class AddUniqueOp extends Op { toAdd.push(v); } } - }) + }); return value.concat(toAdd); } throw new Error('Cannot add elements to a non-array value'); @@ -232,7 +230,7 @@ export class AddUniqueOp extends Op { throw new Error('Cannot merge AddUnique Op with the previous Op'); } - toJSON(): { __op: string; objects: mixed } { + toJSON(): { __op: string, objects: mixed } { return { __op: 'AddUnique', objects: encode(this._value, false, true) }; } } @@ -260,9 +258,7 @@ export class RemoveOp extends Op { } if (this._value[i] instanceof ParseObject && this._value[i].id) { for (let j = 0; j < removed.length; j++) { - if (removed[j] instanceof ParseObject && - this._value[i].id === removed[j].id - ) { + if (removed[j] instanceof ParseObject && this._value[i].id === removed[j].id) { removed.splice(j, 1); j--; } @@ -302,7 +298,7 @@ export class RemoveOp extends Op { throw new Error('Cannot merge Remove Op with the previous Op'); } - toJSON(): { __op: string; objects: mixed } { + toJSON(): { __op: string, objects: mixed } { return { __op: 'Remove', objects: encode(this._value, false, true) }; } } @@ -312,10 +308,7 @@ export class RelationOp extends Op { relationsToAdd: Array; relationsToRemove: Array; - constructor( - adds: Array, - removes: Array - ) { + constructor(adds: Array, removes: Array) { super(); this._targetClassName = null; @@ -333,9 +326,7 @@ export class RelationOp extends Op { return obj; } if (!obj.id) { - throw new Error( - 'You cannot add or remove an unsaved Parse Object from a relation' - ); + throw new Error('You cannot add or remove an unsaved Parse Object from a relation'); } if (!this._targetClassName) { this._targetClassName = obj.className; @@ -343,7 +334,10 @@ export class RelationOp extends Op { if (this._targetClassName !== obj.className) { throw new Error( 'Tried to create a Relation with 2 different object types: ' + - this._targetClassName + ' and ' + obj.className + '.' + this._targetClassName + + ' and ' + + obj.className + + '.' ); } return obj.id; @@ -352,7 +346,9 @@ export class RelationOp extends Op { applyTo(value: mixed, object?: { className: string, id: ?string }, key?: string): ?ParseRelation { if (!value) { if (!object || !key) { - throw new Error('Cannot apply a RelationOp without either a previous value, or an object and a key'); + throw new Error( + 'Cannot apply a RelationOp without either a previous value, or an object and a key' + ); } const parent = new ParseObject(object.className); if (object.id && object.id.indexOf('local') === 0) { @@ -369,8 +365,11 @@ export class RelationOp extends Op { if (value.targetClassName) { if (this._targetClassName !== value.targetClassName) { throw new Error( - 'Related object must be a ' + value.targetClassName + - ', but a ' + this._targetClassName + ' was passed in.' + 'Related object must be a ' + + value.targetClassName + + ', but a ' + + this._targetClassName + + ' was passed in.' ); } } else { @@ -379,9 +378,7 @@ export class RelationOp extends Op { } return value; } else { - throw new Error( - 'Relation cannot be applied to a non-relation field' - ); + throw new Error('Relation cannot be applied to a non-relation field'); } } @@ -393,21 +390,23 @@ export class RelationOp extends Op { } else if (previous instanceof SetOp && previous._value instanceof ParseRelation) { return this; } else if (previous instanceof RelationOp) { - if (previous._targetClassName && - previous._targetClassName !== this._targetClassName) { + if (previous._targetClassName && previous._targetClassName !== this._targetClassName) { throw new Error( - 'Related object must be of class ' + previous._targetClassName + ', but ' + - (this._targetClassName || 'null') + ' was passed in.' + 'Related object must be of class ' + + previous._targetClassName + + ', but ' + + (this._targetClassName || 'null') + + ' was passed in.' ); } const newAdd = previous.relationsToAdd.concat([]); - this.relationsToRemove.forEach((r) => { + this.relationsToRemove.forEach(r => { const index = newAdd.indexOf(r); if (index > -1) { newAdd.splice(index, 1); } }); - this.relationsToAdd.forEach((r) => { + this.relationsToAdd.forEach(r => { const index = newAdd.indexOf(r); if (index < 0) { newAdd.push(r); @@ -415,13 +414,13 @@ export class RelationOp extends Op { }); const newRemove = previous.relationsToRemove.concat([]); - this.relationsToAdd.forEach((r) => { + this.relationsToAdd.forEach(r => { const index = newRemove.indexOf(r); if (index > -1) { newRemove.splice(index, 1); } }); - this.relationsToRemove.forEach((r) => { + this.relationsToRemove.forEach(r => { const index = newRemove.indexOf(r); if (index < 0) { newRemove.push(r); @@ -435,12 +434,12 @@ export class RelationOp extends Op { throw new Error('Cannot merge Relation Op with the previous Op'); } - toJSON(): { __op?: string; objects?: mixed; ops?: mixed } { - const idToPointer = (id) => { + toJSON(): { __op?: string, objects?: mixed, ops?: mixed } { + const idToPointer = id => { return { __type: 'Pointer', className: this._targetClassName, - objectId: id + objectId: id, }; }; diff --git a/src/ParsePolygon.js b/src/ParsePolygon.js index 265900704..b817be8a8 100644 --- a/src/ParsePolygon.js +++ b/src/ParsePolygon.js @@ -36,9 +36,7 @@ class ParsePolygon { /** * @param {(number[][] | Parse.GeoPoint[])} coordinates An Array of coordinate pairs */ - constructor( - coordinates: Array> | Array, - ) { + constructor(coordinates: Array> | Array) { this._coordinates = ParsePolygon._validate(coordinates); } @@ -62,7 +60,7 @@ class ParsePolygon { * * @returns {object} */ - toJSON(): { __type: string; coordinates: Array>;} { + toJSON(): { __type: string, coordinates: Array> } { ParsePolygon._validate(this._coordinates); return { __type: 'Polygon', @@ -77,14 +75,16 @@ class ParsePolygon { * @returns {boolean} */ equals(other: mixed): boolean { - if (!(other instanceof ParsePolygon) || (this.coordinates.length !== other.coordinates.length)) { + if (!(other instanceof ParsePolygon) || this.coordinates.length !== other.coordinates.length) { return false; } let isEqual = true; for (let i = 1; i < this._coordinates.length; i += 1) { - if (this._coordinates[i][0] != other.coordinates[i][0] || - this._coordinates[i][1] != other.coordinates[i][1]) { + if ( + this._coordinates[i][0] != other.coordinates[i][0] || + this._coordinates[i][1] != other.coordinates[i][1] + ) { isEqual = false; break; } @@ -111,20 +111,25 @@ class ParsePolygon { maxY = Math.max(p[1], maxY); } - const outside = (point.latitude < minX || point.latitude > maxX || point.longitude < minY || point.longitude > maxY); + const outside = + point.latitude < minX || + point.latitude > maxX || + point.longitude < minY || + point.longitude > maxY; if (outside) { return false; } let inside = false; - for (let i = 0, j = this._coordinates.length - 1 ; i < this._coordinates.length; j = i++) { + for (let i = 0, j = this._coordinates.length - 1; i < this._coordinates.length; j = i++) { const startX = this._coordinates[i][0]; const startY = this._coordinates[i][1]; const endX = this._coordinates[j][0]; const endY = this._coordinates[j][1]; - const intersect = ((startY > point.longitude) != (endY > point.longitude) && - point.latitude < (endX - startX) * (point.longitude - startY) / (endY - startY) + startX); + const intersect = + startY > point.longitude != endY > point.longitude && + point.latitude < ((endX - startX) * (point.longitude - startY)) / (endY - startY) + startX; if (intersect) { inside = !inside; diff --git a/src/ParseQuery.js b/src/ParseQuery.js index 93712a57b..62c63293b 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -24,24 +24,24 @@ import type { RequestOptions, FullOptions } from './RESTController'; type BatchOptions = FullOptions & { batchSize?: number }; export type WhereClause = { - [attr: string]: mixed; + [attr: string]: mixed, }; export type QueryJSON = { - where: WhereClause; - include?: string; - excludeKeys?: string; - keys?: string; - limit?: number; - skip?: number; - order?: string; - className?: string; - count?: number; - hint? : mixed; - explain? : boolean; - readPreference?: string; - includeReadPreference?: string; - subqueryReadPreference?: string; + where: WhereClause, + include?: string, + excludeKeys?: string, + keys?: string, + limit?: number, + skip?: number, + order?: string, + className?: string, + count?: number, + hint?: mixed, + explain?: boolean, + readPreference?: string, + includeReadPreference?: string, + subqueryReadPreference?: string, }; /** @@ -67,7 +67,7 @@ function quote(s: string): string { */ function _getClassNameFromQueries(queries: Array): ?string { let className = null; - queries.forEach((q) => { + queries.forEach(q => { if (!className) { className = q.className; } @@ -84,18 +84,18 @@ function _getClassNameFromQueries(queries: Array): ?string { * making sure that the data object contains keys for all objects that have * been requested with a select, so that our cached state updates correctly. */ -function handleSelectResult(data: any, select: Array){ +function handleSelectResult(data: any, select: Array) { const serverDataMask = {}; - select.forEach((field) => { - const hasSubObjectSelect = field.indexOf(".") !== -1; - if (!hasSubObjectSelect && !data.hasOwnProperty(field)){ + select.forEach(field => { + const hasSubObjectSelect = field.indexOf('.') !== -1; + if (!hasSubObjectSelect && !data.hasOwnProperty(field)) { // this field was selected, but is missing from the retrieved data - data[field] = undefined + data[field] = undefined; } else if (hasSubObjectSelect) { // this field references a sub-object, // so we need to walk down the path components - const pathComponents = field.split("."); + const pathComponents = field.split('.'); let obj = data; let serverMask = serverDataMask; @@ -125,18 +125,21 @@ function handleSelectResult(data: any, select: Array){ // missing selected keys to sub-objects, but we still need to add in the // data for any previously retrieved sub-objects that were not selected. - const serverData = CoreManager.getObjectStateController().getServerData({id:data.objectId, className:data.className}); + const serverData = CoreManager.getObjectStateController().getServerData({ + id: data.objectId, + className: data.className, + }); copyMissingDataWithMask(serverData, data, serverDataMask, false); } } -function copyMissingDataWithMask(src, dest, mask, copyThisLevel){ +function copyMissingDataWithMask(src, dest, mask, copyThisLevel) { //copy missing elements at this level if (copyThisLevel) { for (const key in src) { if (src.hasOwnProperty(key) && !dest.hasOwnProperty(key)) { - dest[key] = src[key] + dest[key] = src[key]; } } } @@ -161,7 +164,7 @@ function handleOfflineSort(a, b, sorts) { if (order === '_updated_at') { order = 'updatedAt'; } - if (!(/^[A-Za-z][0-9A-Za-z_]*$/).test(order) || order === 'password') { + if (!/^[A-Za-z][0-9A-Za-z_]*$/.test(order) || order === 'password') { throw new ParseError(ParseError.INVALID_KEY_NAME, `Invalid Key: ${order}`); } const field1 = a.get(order); @@ -265,9 +268,7 @@ class ParseQuery { this.className = obj.className; } } else { - throw new TypeError( - 'A ParseQuery must be constructed with a ParseObject or class name.' - ); + throw new TypeError('A ParseQuery must be constructed with a ParseObject or class name.'); } this._where = {}; @@ -285,7 +286,7 @@ class ParseQuery { this._xhrRequest = { task: null, onchange: () => {}, - } + }; } /** @@ -295,7 +296,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ _orQuery(queries: Array): ParseQuery { - const queryJSON = queries.map((q) => { + const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -310,7 +311,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ _andQuery(queries: Array): ParseQuery { - const queryJSON = queries.map((q) => { + const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -325,7 +326,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ _norQuery(queries: Array): ParseQuery { - const queryJSON = queries.map((q) => { + const queryJSON = queries.map(q => { return q.toJSON().where; }); @@ -363,23 +364,25 @@ class ParseQuery { OfflineQuery.validateQuery(this); const localDatastore = CoreManager.getLocalDatastore(); const objects = await localDatastore._serializeObjectsFromPinName(this._localDatastorePinName); - let results = objects.map((json, index, arr) => { - const object = ParseObject.fromJSON(json, false); - if (json._localId && !json.objectId) { - object._localId = json._localId; - } - if (!OfflineQuery.matchesQuery(this.className, object, arr, this)) { - return null; - } - return object; - }).filter((object) => object !== null); + let results = objects + .map((json, index, arr) => { + const object = ParseObject.fromJSON(json, false); + if (json._localId && !json.objectId) { + object._localId = json._localId; + } + if (!OfflineQuery.matchesQuery(this.className, object, arr, this)) { + return null; + } + return object; + }) + .filter(object => object !== null); if (params.keys) { let keys = params.keys.split(','); const alwaysSelectedKeys = ['className', 'objectId', 'createdAt', 'updatedAt', 'ACL']; keys = keys.concat(alwaysSelectedKeys); - results = results.map((object) => { + results = results.map(object => { const json = object._toFullJSON(); - Object.keys(json).forEach((key) => { + Object.keys(json).forEach(key => { if (!keys.includes(key)) { delete json[key]; } @@ -394,8 +397,8 @@ class ParseQuery { }); } - let count // count total before applying limit/skip - if(params.count){ + let count; // count total before applying limit/skip + if (params.count) { count = results.length; // total count from response } @@ -413,8 +416,8 @@ class ParseQuery { results = results.splice(0, limit); - if(typeof count === 'number'){ - return {results, count}; + if (typeof count === 'number') { + return { results, count }; } return results; @@ -427,7 +430,7 @@ class ParseQuery { */ toJSON(): QueryJSON { const params: QueryJSON = { - where: this._where + where: this._where, }; if (this._include.length) { @@ -495,21 +498,20 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ withJSON(json: QueryJSON): ParseQuery { - if (json.where) { this._where = json.where; } if (json.include) { - this._include = json.include.split(","); + this._include = json.include.split(','); } if (json.keys) { - this._select = json.keys.split(","); + this._select = json.keys.split(','); } if (json.excludeKeys) { - this._exclude = json.excludeKeys.split(","); + this._exclude = json.excludeKeys.split(','); } if (json.count) { @@ -517,7 +519,7 @@ class ParseQuery { } if (json.limit) { - this._limit = json.limit; + this._limit = json.limit; } if (json.skip) { @@ -525,7 +527,7 @@ class ParseQuery { } if (json.order) { - this._order = json.order.split(","); + this._order = json.order.split(','); } if (json.readPreference) { @@ -549,15 +551,29 @@ class ParseQuery { } for (const key in json) { - if (json.hasOwnProperty(key)) { - if (["where", "include", "keys", "count", "limit", "skip", "order", "readPreference", "includeReadPreference", "subqueryReadPreference", "hint", "explain"].indexOf(key) === -1) { + if (json.hasOwnProperty(key)) { + if ( + [ + 'where', + 'include', + 'keys', + 'count', + 'limit', + 'skip', + 'order', + 'readPreference', + 'includeReadPreference', + 'subqueryReadPreference', + 'hint', + 'explain', + ].indexOf(key) === -1 + ) { this._extraOptions[key] = json[key]; } } } return this; - } /** @@ -604,15 +620,12 @@ class ParseQuery { firstOptions.context = options.context; } - return this.first(firstOptions).then((response) => { + return this.first(firstOptions).then(response => { if (response) { return response; } - const errorObject = new ParseError( - ParseError.OBJECT_NOT_FOUND, - 'Object not found.' - ); + const errorObject = new ParseError(ParseError.OBJECT_NOT_FOUND, 'Object not found.'); return Promise.reject(errorObject); }); } @@ -654,16 +667,12 @@ class ParseQuery { if (this._queriesLocalDatastore) { return this._handleOfflineQuery(this.toJSON()); } - return controller.find( - this.className, - this.toJSON(), - findOptions - ).then((response) => { + return controller.find(this.className, this.toJSON(), findOptions).then(response => { // Return generic object when explain is used if (this._explain) { return response.results; } - const results = response.results.map((data) => { + const results = response.results.map(data => { // In cases of relations, the server may send back a className // on the top level of the payload const override = response.className || this.className; @@ -683,8 +692,8 @@ class ParseQuery { const count = response.count; - if(typeof count === "number"){ - return {results, count}; + if (typeof count === 'number') { + return { results, count }; } else { return results; } @@ -745,11 +754,7 @@ class ParseQuery { params.limit = 0; params.count = 1; - return controller.find( - this.className, - params, - findOptions - ).then((result) => { + return controller.find(this.className, params, findOptions).then(result => { return result.count; }); } @@ -783,11 +788,7 @@ class ParseQuery { where: this._where, hint: this._hint, }; - return controller.aggregate( - this.className, - params, - distinctOptions - ).then((results) => { + return controller.aggregate(this.className, params, distinctOptions).then(results => { return results.results; }); } @@ -830,13 +831,9 @@ class ParseQuery { pipeline, hint: this._hint, explain: this._explain, - readPreference: this._readPreference + readPreference: this._readPreference, }; - return controller.aggregate( - this.className, - params, - aggregateOptions, - ).then((results) => { + return controller.aggregate(this.className, params, aggregateOptions).then(results => { return results.results; }); } @@ -880,7 +877,7 @@ class ParseQuery { const select = this._select; if (this._queriesLocalDatastore) { - return this._handleOfflineQuery(params).then((objects) => { + return this._handleOfflineQuery(params).then(objects => { if (!objects[0]) { return undefined; } @@ -888,11 +885,7 @@ class ParseQuery { }); } - return controller.find( - this.className, - params, - findOptions - ).then((response) => { + return controller.find(this.className, params, findOptions).then(response => { const objects = response.results; if (!objects[0]) { return undefined; @@ -933,21 +926,24 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - eachBatch(callback: (objs: Array) => Promise<*>, options?: BatchOptions): Promise { + eachBatch( + callback: (objs: Array) => Promise<*>, + options?: BatchOptions + ): Promise { options = options || {}; - if (this._order || this._skip || (this._limit >= 0)) { + if (this._order || this._skip || this._limit >= 0) { const error = 'Cannot iterate on a query with sort, skip, or limit.'; return Promise.reject(error); } const query = new ParseQuery(this.className); query._limit = options.batchSize || 100; - query._include = this._include.map((i) => { + query._include = this._include.map(i => { return i; }); if (this._select) { - query._select = this._select.map((s) => { + query._select = this._select.map(s => { return s; }); } @@ -956,7 +952,7 @@ class ParseQuery { for (const attr in this._where) { const val = this._where[attr]; if (Array.isArray(val)) { - query._where[attr] = val.map((v) => { + query._where[attr] = val.map(v => { return v; }); } else if (val && typeof val === 'object') { @@ -985,23 +981,26 @@ class ParseQuery { let finished = false; let previousResults = []; - return continueWhile(() => { - return !finished; - }, async () => { - const [results] = await Promise.all([ - query.find(findOptions), - Promise.resolve(previousResults.length > 0 && callback(previousResults)) - ]); - if (results.length >= query._limit) { - query.greaterThan('objectId', results[results.length - 1].id); - previousResults = results; - } else if (results.length > 0) { - await Promise.resolve(callback(results)); - finished = true; - } else { - finished = true; + return continueWhile( + () => { + return !finished; + }, + async () => { + const [results] = await Promise.all([ + query.find(findOptions), + Promise.resolve(previousResults.length > 0 && callback(previousResults)), + ]); + if (results.length >= query._limit) { + query.greaterThan('objectId', results[results.length - 1].id); + previousResults = results; + } else if (results.length > 0) { + await Promise.resolve(callback(results)); + finished = true; + } else { + finished = true; + } } - }); + ); } /** @@ -1024,9 +1023,9 @@ class ParseQuery { * iteration has completed. */ each(callback: (obj: ParseObject) => any, options?: BatchOptions): Promise { - return this.eachBatch((results) => { + return this.eachBatch(results => { let callbacksDone = Promise.resolve(); - results.forEach((result) => { + results.forEach(result => { callbacksDone = callbacksDone.then(() => { return callback(result); }); @@ -1086,11 +1085,14 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - async map(callback: (currentObject: ParseObject, index: number, query: ParseQuery) => any, options?: BatchOptions): Promise> { + async map( + callback: (currentObject: ParseObject, index: number, query: ParseQuery) => any, + options?: BatchOptions + ): Promise> { const array = []; let index = 0; - await this.each((object) => { - return Promise.resolve(callback(object, index, this)).then((result) => { + await this.each(object => { + return Promise.resolve(callback(object, index, this)).then(result => { array.push(result); index += 1; }); @@ -1121,10 +1123,14 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - async reduce(callback: (accumulator: any, currentObject: ParseObject, index: number) => any, initialValue: any, options?: BatchOptions): Promise> { + async reduce( + callback: (accumulator: any, currentObject: ParseObject, index: number) => any, + initialValue: any, + options?: BatchOptions + ): Promise> { let accumulator = initialValue; let index = 0; - await this.each((object) => { + await this.each(object => { // If no initial value was given, we take the first object from the query // as the initial value and don't call the callback with it. if (index === 0 && initialValue === undefined) { @@ -1132,7 +1138,7 @@ class ParseQuery { index += 1; return; } - return Promise.resolve(callback(accumulator, object, index)).then((result) => { + return Promise.resolve(callback(accumulator, object, index)).then(result => { accumulator = result; index += 1; }); @@ -1140,7 +1146,7 @@ class ParseQuery { if (index === 0 && initialValue === undefined) { // Match Array.reduce behavior: "Calling reduce() on an empty array // without an initialValue will throw a TypeError". - throw new TypeError("Reducing empty query result set with no initial value"); + throw new TypeError('Reducing empty query result set with no initial value'); } return accumulator; } @@ -1168,11 +1174,14 @@ class ParseQuery { * @returns {Promise} A promise that will be fulfilled once the * iteration has completed. */ - async filter(callback: (currentObject: ParseObject, index: number, query: ParseQuery) => boolean, options?: BatchOptions): Promise> { + async filter( + callback: (currentObject: ParseObject, index: number, query: ParseQuery) => boolean, + options?: BatchOptions + ): Promise> { const array = []; let index = 0; - await this.each((object) => { - return Promise.resolve(callback(object, index, this)).then((flag) => { + await this.each(object => { + return Promise.resolve(callback(object, index, this)).then(flag => { if (flag) { array.push(object); } @@ -1194,8 +1203,8 @@ class ParseQuery { */ equalTo(key: string | { [key: string]: any }, value: ?mixed): ParseQuery { if (key && typeof key === 'object') { - Object.entries(key).forEach(([k, val]) => this.equalTo(k, val)) - return this + Object.entries(key).forEach(([k, val]) => this.equalTo(k, val)); + return this; } if (typeof value === 'undefined') { return this.doesNotExist(key); @@ -1215,8 +1224,8 @@ class ParseQuery { */ notEqualTo(key: string | { [key: string]: any }, value: ?mixed): ParseQuery { if (key && typeof key === 'object') { - Object.entries(key).forEach(([k, val]) => this.notEqualTo(k, val)) - return this + Object.entries(key).forEach(([k, val]) => this.notEqualTo(k, val)); + return this; } return this._addCondition(key, '$ne', value); } @@ -1331,8 +1340,8 @@ class ParseQuery { values = [values]; } - const regexObject = values.map((value) => { - return { '$regex': _this._regexStartWith(value) }; + const regexObject = values.map(value => { + return { $regex: _this._regexStartWith(value) }; }); return this.containsAll(key, regexObject); @@ -1431,7 +1440,7 @@ class ParseQuery { queryJSON.className = query.className; return this._addCondition(key, '$select', { key: queryKey, - query: queryJSON + query: queryJSON, }); } @@ -1451,7 +1460,7 @@ class ParseQuery { queryJSON.className = query.className; return this._addCondition(key, '$dontSelect', { key: queryKey, - query: queryJSON + query: queryJSON, }); } @@ -1604,12 +1613,19 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinRadians(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery { + withinRadians( + key: string, + point: ParseGeoPoint, + maxDistance: number, + sorted: boolean + ): ParseQuery { if (sorted || sorted === undefined) { this.near(key, point); return this._addCondition(key, '$maxDistance', maxDistance); } else { - return this._addCondition(key, '$geoWithin', { '$centerSphere': [[point.longitude, point.latitude], maxDistance] }); + return this._addCondition(key, '$geoWithin', { + $centerSphere: [[point.longitude, point.latitude], maxDistance], + }); } } @@ -1643,7 +1659,12 @@ class ParseQuery { * defaults to true. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - withinKilometers(key: string, point: ParseGeoPoint, maxDistance: number, sorted: boolean): ParseQuery { + withinKilometers( + key: string, + point: ParseGeoPoint, + maxDistance: number, + sorted: boolean + ): ParseQuery { return this.withinRadians(key, point, maxDistance / 6371.0, sorted); } @@ -1666,7 +1687,7 @@ class ParseQuery { if (!(northeast instanceof ParseGeoPoint)) { northeast = new ParseGeoPoint(northeast); } - this._addCondition(key, '$within', { '$box': [ southwest, northeast ] }); + this._addCondition(key, '$within', { $box: [southwest, northeast] }); return this; } @@ -1682,7 +1703,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ withinPolygon(key: string, points: Array>): ParseQuery { - return this._addCondition(key, '$geoWithin', { '$polygon': points }); + return this._addCondition(key, '$geoWithin', { $polygon: points }); } /** @@ -1694,7 +1715,7 @@ class ParseQuery { * @returns {Parse.Query} Returns the query, so you can chain this call. */ polygonContains(key: string, point: ParseGeoPoint): ParseQuery { - return this._addCondition(key, '$geoIntersects', { '$point': point }); + return this._addCondition(key, '$geoIntersects', { $point: point }); } /** Query Orderings **/ @@ -1723,7 +1744,7 @@ class ParseQuery { if (!this._order) { this._order = []; } - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { key = key.join(); } @@ -1757,14 +1778,17 @@ class ParseQuery { if (!this._order) { this._order = []; } - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { key = key.join(); } this._order = this._order.concat( - key.replace(/\s/g, '').split(',').map((k) => { - return '-' + k; - }) + key + .replace(/\s/g, '') + .split(',') + .map(k => { + return '-' + k; + }) ); }); @@ -1830,8 +1854,8 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - include(...keys: Array>): ParseQuery { - keys.forEach((key) => { + include(...keys: Array>): ParseQuery { + keys.forEach(key => { if (Array.isArray(key)) { this._include = this._include.concat(key); } else { @@ -1860,11 +1884,11 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to include. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - select(...keys: Array>): ParseQuery { + select(...keys: Array>): ParseQuery { if (!this._select) { this._select = []; } - keys.forEach((key) => { + keys.forEach(key => { if (Array.isArray(key)) { this._select = this._select.concat(key); } else { @@ -1883,8 +1907,8 @@ class ParseQuery { * @param {...string|Array} keys The name(s) of the key(s) to exclude. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - exclude(...keys: Array>): ParseQuery { - keys.forEach((key) => { + exclude(...keys: Array>): ParseQuery { + keys.forEach(key => { if (Array.isArray(key)) { this._exclude = this._exclude.concat(key); } else { @@ -1902,7 +1926,11 @@ class ParseQuery { * @param {string} subqueryReadPreference The read preference for the sub queries. * @returns {Parse.Query} Returns the query, so you can chain this call. */ - readPreference(readPreference: string, includeReadPreference?: string, subqueryReadPreference?: string): ParseQuery { + readPreference( + readPreference: string, + includeReadPreference?: string, + subqueryReadPreference?: string + ): ParseQuery { this._readPreference = readPreference; this._includeReadPreference = includeReadPreference; this._subqueryReadPreference = subqueryReadPreference; @@ -1919,7 +1947,7 @@ class ParseQuery { async subscribe(sessionToken?: string): Promise { const currentUser = await CoreManager.getUserController().currentUserAsync(); if (!sessionToken) { - sessionToken = currentUser ? currentUser.getSessionToken() : undefined; + sessionToken = currentUser ? currentUser.getSessionToken() : undefined; } const liveQueryClient = await CoreManager.getLiveQueryController().getDefaultLiveQueryClient(); if (liveQueryClient.shouldOpen()) { @@ -2045,11 +2073,11 @@ class ParseQuery { this._xhrRequest.onchange = () => {}; return this; } - return this._xhrRequest.onchange = () => this.cancel(); + return (this._xhrRequest.onchange = () => this.cancel()); } _setRequestTask(options) { - options.requestTask = (task) => { + options.requestTask = task => { this._xhrRequest.task = task; this._xhrRequest.onchange(); }; @@ -2059,24 +2087,14 @@ class ParseQuery { const DefaultController = { find(className: string, params: QueryJSON, options: RequestOptions): Promise> { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', - 'classes/' + className, - params, - options - ); + return RESTController.request('GET', 'classes/' + className, params, options); }, aggregate(className: string, params: any, options: RequestOptions): Promise> { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', - 'aggregate/' + className, - params, - options - ); - } + return RESTController.request('GET', 'aggregate/' + className, params, options); + }, }; CoreManager.setQueryController(DefaultController); diff --git a/src/ParseRelation.js b/src/ParseRelation.js index 6cb2b741e..e467c92c2 100644 --- a/src/ParseRelation.js +++ b/src/ParseRelation.js @@ -47,21 +47,15 @@ class ParseRelation { _ensureParentAndKey(parent: ParseObject, key: string) { this.key = this.key || key; if (this.key !== key) { - throw new Error( - 'Internal Error. Relation retrieved from two different keys.' - ); + throw new Error('Internal Error. Relation retrieved from two different keys.'); } if (this.parent) { if (this.parent.className !== parent.className) { - throw new Error( - 'Internal Error. Relation retrieved from two different Objects.' - ); + throw new Error('Internal Error. Relation retrieved from two different Objects.'); } if (this.parent.id) { if (this.parent.id !== parent.id) { - throw new Error( - 'Internal Error. Relation retrieved from two different Objects.' - ); + throw new Error('Internal Error. Relation retrieved from two different Objects.'); } } else if (parent.id) { this.parent = parent; @@ -124,7 +118,7 @@ class ParseRelation { toJSON(): { __type: 'Relation', className: ?string } { return { __type: 'Relation', - className: this.targetClassName + className: this.targetClassName, }; } @@ -144,12 +138,12 @@ class ParseRelation { query = new ParseQuery(parent.className); query._extraOptions.redirectClassNameForKey = this.key; } else { - query = new ParseQuery(this.targetClassName) + query = new ParseQuery(this.targetClassName); } query._addCondition('$relatedTo', 'object', { __type: 'Pointer', className: parent.className, - objectId: parent.id + objectId: parent.id, }); query._addCondition('$relatedTo', 'key', this.key); diff --git a/src/ParseRole.js b/src/ParseRole.js index 72fcfd2f4..07d4c8fa2 100644 --- a/src/ParseRole.js +++ b/src/ParseRole.js @@ -38,7 +38,7 @@ class ParseRole extends ParseObject { */ constructor(name: string, acl: ParseACL) { super('_Role'); - if (typeof name === 'string' && (acl instanceof ParseACL)) { + if (typeof name === 'string' && acl instanceof ParseACL) { this.setName(name); this.setACL(acl); } @@ -122,20 +122,16 @@ class ParseRole extends ParseObject { // Let the name be set in this case return new ParseError( ParseError.OTHER_CAUSE, - 'A role\'s name can only be set before it has been saved.' + "A role's name can only be set before it has been saved." ); } if (typeof newName !== 'string') { - return new ParseError( - ParseError.OTHER_CAUSE, - 'A role\'s name must be a String.' - ); + return new ParseError(ParseError.OTHER_CAUSE, "A role's name must be a String."); } - if (!(/^[0-9a-zA-Z\-_ ]+$/).test(newName)) { + if (!/^[0-9a-zA-Z\-_ ]+$/.test(newName)) { return new ParseError( ParseError.OTHER_CAUSE, - 'A role\'s name can be only contain alphanumeric characters, _, ' + - '-, and spaces.' + "A role's name can be only contain alphanumeric characters, _, " + '-, and spaces.' ); } } diff --git a/src/ParseSchema.js b/src/ParseSchema.js index 227d7cb20..6d770e903 100644 --- a/src/ParseSchema.js +++ b/src/ParseSchema.js @@ -12,11 +12,23 @@ import CoreManager from './CoreManager'; import ParseObject from './ParseObject'; -const FIELD_TYPES = ['String', 'Number', 'Boolean', 'Date', 'File', 'GeoPoint', 'Polygon', 'Array', 'Object', 'Pointer', 'Relation']; +const FIELD_TYPES = [ + 'String', + 'Number', + 'Boolean', + 'Date', + 'File', + 'GeoPoint', + 'Polygon', + 'Array', + 'Object', + 'Pointer', + 'Relation', +]; type FieldOptions = { - required: boolean; - defaultValue: mixed; + required: boolean, + defaultValue: mixed, }; /** @@ -66,13 +78,12 @@ class ParseSchema { */ static all() { const controller = CoreManager.getSchemaController(); - return controller.get('') - .then((response) => { - if (response.results.length === 0) { - throw new Error('Schema not found.'); - } - return response.results; - }); + return controller.get('').then(response => { + if (response.results.length === 0) { + throw new Error('Schema not found.'); + } + return response.results; + }); } /** @@ -85,13 +96,12 @@ class ParseSchema { this.assertClassName(); const controller = CoreManager.getSchemaController(); - return controller.get(this.className) - .then((response) => { - if (!response) { - throw new Error('Schema not found.'); - } - return response; - }); + return controller.get(this.className).then(response => { + if (!response) { + throw new Error('Schema not found.'); + } + return response; + }); } /** @@ -287,7 +297,10 @@ class ParseSchema { */ addDate(name: string, options: FieldOptions) { if (options && options.defaultValue) { - options.defaultValue = { __type: 'Date', iso: new Date(options.defaultValue) } + options.defaultValue = { + __type: 'Date', + iso: new Date(options.defaultValue), + }; } return this.addField(name, 'Date', options); } @@ -394,7 +407,7 @@ class ParseSchema { this._fields[name] = { type: 'Relation', - targetClass + targetClass, }; return this; @@ -407,7 +420,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ deleteField(name: string) { - this._fields[name] = { __op: 'Delete'}; + this._fields[name] = { __op: 'Delete' }; return this; } @@ -418,7 +431,7 @@ class ParseSchema { * @returns {Parse.Schema} Returns the schema, so you can chain this call. */ deleteIndex(name: string) { - this._indexes[name] = { __op: 'Delete'}; + this._indexes[name] = { __op: 'Delete' }; return this; } } @@ -426,12 +439,9 @@ class ParseSchema { const DefaultController = { send(className: string, method: string, params: any = {}): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - method, - `schemas/${className}`, - params, - { useMasterKey: true } - ); + return RESTController.request(method, `schemas/${className}`, params, { + useMasterKey: true, + }); }, get(className: string): Promise { @@ -452,13 +462,8 @@ const DefaultController = { purge(className: string): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'DELETE', - `purge/${className}`, - {}, - { useMasterKey: true } - ); - } + return RESTController.request('DELETE', `purge/${className}`, {}, { useMasterKey: true }); + }, }; CoreManager.setSchemaController(DefaultController); diff --git a/src/ParseSession.js b/src/ParseSession.js index 561309d64..1b1d8d108 100644 --- a/src/ParseSession.js +++ b/src/ParseSession.js @@ -31,9 +31,9 @@ class ParseSession extends ParseObject { */ constructor(attributes: ?AttributeMap) { super('_Session'); - if (attributes && typeof attributes === 'object'){ + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { - throw new Error('Can\'t create an invalid Session'); + throw new Error("Can't create an invalid Session"); } } } @@ -52,14 +52,7 @@ class ParseSession extends ParseObject { } static readOnlyAttributes() { - return [ - 'createdWith', - 'expiresAt', - 'installationId', - 'restricted', - 'sessionToken', - 'user' - ]; + return ['createdWith', 'expiresAt', 'installationId', 'restricted', 'sessionToken', 'user']; } /** @@ -79,7 +72,7 @@ class ParseSession extends ParseObject { if (options.hasOwnProperty('useMasterKey')) { sessionOptions.useMasterKey = options.useMasterKey; } - return ParseUser.currentAsync().then((user) => { + return ParseUser.currentAsync().then(user => { if (!user) { return Promise.reject('There is no current user.'); } @@ -114,14 +107,12 @@ const DefaultController = { const RESTController = CoreManager.getRESTController(); const session = new ParseSession(); - return RESTController.request( - 'GET', 'sessions/me', {}, options - ).then((sessionData) => { + return RESTController.request('GET', 'sessions/me', {}, options).then(sessionData => { session._finishFetch(sessionData); session._setExisted(true); return session; }); - } + }, }; CoreManager.setSessionController(DefaultController); diff --git a/src/ParseUser.js b/src/ParseUser.js index 115eeff1b..65e6444f0 100644 --- a/src/ParseUser.js +++ b/src/ParseUser.js @@ -45,9 +45,9 @@ class ParseUser extends ParseObject { */ constructor(attributes: ?AttributeMap) { super('_User'); - if (attributes && typeof attributes === 'object'){ + if (attributes && typeof attributes === 'object') { if (!this.set(attributes || {})) { - throw new Error('Can\'t create an invalid Parse User'); + throw new Error("Can't create an invalid Parse User"); } } } @@ -68,10 +68,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.upgradeToRevocableSession( - this, - upgradeOptions - ); + return controller.upgradeToRevocableSession(this, upgradeOptions); } /** @@ -89,7 +86,11 @@ class ParseUser extends ParseObject { * @param {object} saveOpts useMasterKey / sessionToken * @returns {Promise} A promise that is fulfilled with the user is linked */ - linkWith(provider: any, options: { authData?: AuthData }, saveOpts?: FullOptions = {}): Promise { + linkWith( + provider: any, + options: { authData?: AuthData }, + saveOpts?: FullOptions = {} + ): Promise { saveOpts.sessionToken = saveOpts.sessionToken || this.getSessionToken() || ''; let authType; if (typeof provider === 'string') { @@ -119,26 +120,25 @@ class ParseUser extends ParseObject { authData[authType] = options.authData; const controller = CoreManager.getUserController(); - return controller.linkWith( - this, - authData, - saveOpts - ); + return controller.linkWith(this, authData, saveOpts); } else { return new Promise((resolve, reject) => { provider.authenticate({ success: (provider, result) => { const opts = {}; opts.authData = result; - this.linkWith(provider, opts, saveOpts).then(() => { - resolve(this); - }, (error) => { - reject(error); - }); + this.linkWith(provider, opts, saveOpts).then( + () => { + resolve(this); + }, + error => { + reject(error); + } + ); }, error: (provider, error) => { reject(error); - } + }, }); }); } @@ -151,7 +151,11 @@ class ParseUser extends ParseObject { * @deprecated since 2.9.0 see {@link https://parseplatform.org/Parse-SDK-JS/api/master/Parse.User.html#linkWith linkWith} * @returns {Promise} */ - _linkWith(provider: any, options: { authData?: AuthData }, saveOpts?: FullOptions = {}): Promise { + _linkWith( + provider: any, + options: { authData?: AuthData }, + saveOpts?: FullOptions = {} + ): Promise { return this.linkWith(provider, options, saveOpts); } @@ -387,11 +391,7 @@ class ParseUser extends ParseObject { */ authenticated(): boolean { const current = ParseUser.current(); - return ( - !!this.get('sessionToken') && - !!current && - current.id === this.id - ); + return !!this.get('sessionToken') && !!current && current.id === this.id; } /** @@ -419,11 +419,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.signUp( - this, - attrs, - signupOptions - ); + return controller.signUp(this, attrs, signupOptions); } /** @@ -545,7 +541,7 @@ class ParseUser extends ParseObject { * @static * @returns {Parse.User} The newly extended Parse.User class */ - static extend(protoProps: {[prop: string]: any}, classProps: {[prop: string]: any}) { + static extend(protoProps: { [prop: string]: any }, classProps: { [prop: string]: any }) { if (protoProps) { for (const prop in protoProps) { if (prop !== 'className') { @@ -553,7 +549,7 @@ class ParseUser extends ParseObject { value: protoProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -566,7 +562,7 @@ class ParseUser extends ParseObject { value: classProps[prop], enumerable: false, writable: true, - configurable: true + configurable: true, }); } } @@ -641,19 +637,9 @@ class ParseUser extends ParseObject { */ static logIn(username: string, password: string, options?: FullOptions) { if (typeof username !== 'string') { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Username must be a string.' - ) - ); + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Username must be a string.')); } else if (typeof password !== 'string') { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Password must be a string.' - ) - ); + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } const user = new this(); user._finishFetch({ username: username, password: password }); @@ -673,14 +659,12 @@ class ParseUser extends ParseObject { */ static become(sessionToken: string, options?: RequestOptions) { if (!canUseCurrentUser) { - throw new Error( - 'It is not memory-safe to become a user in a server environment' - ); + throw new Error('It is not memory-safe to become a user in a server environment'); } options = options || {}; const becomeOptions: RequestOptions = { - sessionToken: sessionToken + sessionToken: sessionToken, }; if (options.hasOwnProperty('useMasterKey')) { becomeOptions.useMasterKey = options.useMasterKey; @@ -702,7 +686,7 @@ class ParseUser extends ParseObject { static me(sessionToken: string, options?: RequestOptions = {}) { const controller = CoreManager.getUserController(); const meOptions: RequestOptions = { - sessionToken: sessionToken + sessionToken: sessionToken, }; if (options.useMasterKey) { meOptions.useMasterKey = options.useMasterKey; @@ -736,7 +720,11 @@ class ParseUser extends ParseObject { * @static * @returns {Promise} */ - static logInWith(provider: any, options: { authData?: AuthData }, saveOpts?: FullOptions): Promise { + static logInWith( + provider: any, + options: { authData?: AuthData }, + saveOpts?: FullOptions + ): Promise { const user = new this(); return user.linkWith(provider, options, saveOpts); } @@ -776,9 +764,7 @@ class ParseUser extends ParseObject { } const controller = CoreManager.getUserController(); - return controller.requestPasswordReset( - email, requestOptions - ); + return controller.requestPasswordReset(email, requestOptions); } /** @@ -814,21 +800,11 @@ class ParseUser extends ParseObject { */ static verifyPassword(username: string, password: string, options?: RequestOptions) { if (typeof username !== 'string') { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Username must be a string.' - ) - ); + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Username must be a string.')); } if (typeof password !== 'string') { - return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Password must be a string.' - ) - ); + return Promise.reject(new ParseError(ParseError.OTHER_CAUSE, 'Password must be a string.')); } options = options || {}; @@ -918,7 +894,7 @@ class ParseUser extends ParseObject { static _registerAuthenticationProvider(provider: any) { authProviders[provider.getAuthType()] = provider; // Synchronize the current user with the auth provider. - ParseUser.currentAsync().then((current) => { + ParseUser.currentAsync().then(current => { if (current) { current._synchronizeAuthData(provider.getAuthType()); } @@ -960,11 +936,9 @@ const DefaultController = { let userData = JSON.stringify(json); if (CoreManager.get('ENCRYPTED_USER')) { const crypto = CoreManager.getCryptoController(); - userData = crypto.encrypt(json, CoreManager.get('ENCRYPTED_KEY')) + userData = crypto.encrypt(json, CoreManager.get('ENCRYPTED_KEY')); } - return Storage.setItemAsync( - path, userData - ).then(() => { + return Storage.setItemAsync(path, userData).then(() => { return user; }); }, @@ -979,7 +953,9 @@ const DefaultController = { async setCurrentUser(user) { const currentUser = await this.currentUserAsync(); if (currentUser && !user.equals(currentUser) && AnonymousUtils.isLinked(currentUser)) { - await currentUser.destroy({ sessionToken: currentUser.getSessionToken() }) + await currentUser.destroy({ + sessionToken: currentUser.getSessionToken(), + }); } currentUserCache = user; user._cleanupAuthData(); @@ -997,7 +973,7 @@ const DefaultController = { if (Storage.async()) { throw new Error( 'Cannot call currentUser() when using a platform with an async ' + - 'storage system. Call currentUserAsync() instead.' + 'storage system. Call currentUserAsync() instead.' ); } const path = Storage.generatePath(CURRENT_USER_KEY); @@ -1033,15 +1009,13 @@ const DefaultController = { currentUserAsync(): Promise { if (currentUserCache) { - return Promise.resolve(currentUserCache) + return Promise.resolve(currentUserCache); } if (currentUserCacheMatchesDisk) { return Promise.resolve(null); } const path = Storage.generatePath(CURRENT_USER_KEY); - return Storage.getItemAsync( - path - ).then((userData) => { + return Storage.getItemAsync(path).then(userData => { currentUserCacheMatchesDisk = true; if (!userData) { currentUserCache = null; @@ -1078,18 +1052,12 @@ const DefaultController = { if (!username || !username.length) { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Cannot sign up user with an empty username.' - ) + new ParseError(ParseError.OTHER_CAUSE, 'Cannot sign up user with an empty username.') ); } if (!password || !password.length) { return Promise.reject( - new ParseError( - ParseError.OTHER_CAUSE, - 'Cannot sign up user with an empty password.' - ) + new ParseError(ParseError.OTHER_CAUSE, 'Cannot sign up user with an empty password.') ); } @@ -1109,34 +1077,28 @@ const DefaultController = { const stateController = CoreManager.getObjectStateController(); const auth = { username: user.get('username'), - password: user.get('password') + password: user.get('password'), }; - return RESTController.request( - options.usePost ? 'POST' : 'GET', 'login', auth, options - ).then((response) => { - user._migrateId(response.objectId); - user._setExisted(true); - stateController.setPendingOp( - user._getStateIdentifier(), 'username', undefined - ); - stateController.setPendingOp( - user._getStateIdentifier(), 'password', undefined - ); - response.password = undefined; - user._finishFetch(response); - if (!canUseCurrentUser) { - // We can't set the current user, so just return the one we logged in - return Promise.resolve(user); + return RESTController.request(options.usePost ? 'POST' : 'GET', 'login', auth, options).then( + response => { + user._migrateId(response.objectId); + user._setExisted(true); + stateController.setPendingOp(user._getStateIdentifier(), 'username', undefined); + stateController.setPendingOp(user._getStateIdentifier(), 'password', undefined); + response.password = undefined; + user._finishFetch(response); + if (!canUseCurrentUser) { + // We can't set the current user, so just return the one we logged in + return Promise.resolve(user); + } + return DefaultController.setCurrentUser(user); } - return DefaultController.setCurrentUser(user); - }); + ); }, become(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'users/me', {}, options - ).then((response) => { + return RESTController.request('GET', 'users/me', {}, options).then(response => { user._finishFetch(response); user._setExisted(true); return DefaultController.setCurrentUser(user); @@ -1155,9 +1117,7 @@ const DefaultController = { me(user: ParseUser, options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', 'users/me', {}, options - ).then((response) => { + return RESTController.request('GET', 'users/me', {}, options).then(response => { user._finishFetch(response); user._setExisted(true); return user; @@ -1167,26 +1127,24 @@ const DefaultController = { logOut(options: RequestOptions): Promise { const RESTController = CoreManager.getRESTController(); if (options.sessionToken) { - return RESTController.request( - 'POST', 'logout', {}, options - ); + return RESTController.request('POST', 'logout', {}, options); } - return DefaultController.currentUserAsync().then((currentUser) => { + return DefaultController.currentUserAsync().then(currentUser => { const path = Storage.generatePath(CURRENT_USER_KEY); let promise = Storage.removeItemAsync(path); if (currentUser !== null) { const isAnonymous = AnonymousUtils.isLinked(currentUser); const currentSession = currentUser.getSessionToken(); if (currentSession && isRevocableSession(currentSession)) { - promise = promise.then(() => { - if (isAnonymous) { - return currentUser.destroy({ sessionToken: currentSession }); - } - }).then(() => { - return RESTController.request( - 'POST', 'logout', {}, { sessionToken: currentSession } - ); - }); + promise = promise + .then(() => { + if (isAnonymous) { + return currentUser.destroy({ sessionToken: currentSession }); + } + }) + .then(() => { + return RESTController.request('POST', 'logout', {}, { sessionToken: currentSession }); + }); } currentUser._logOutWithAll(); currentUser._finishFetch({ sessionToken: undefined }); @@ -1200,34 +1158,21 @@ const DefaultController = { requestPasswordReset(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'POST', - 'requestPasswordReset', - { email: email }, - options - ); + return RESTController.request('POST', 'requestPasswordReset', { email: email }, options); }, upgradeToRevocableSession(user: ParseUser, options: RequestOptions) { const token = user.getSessionToken(); if (!token) { return Promise.reject( - new ParseError( - ParseError.SESSION_MISSING, - 'Cannot upgrade a user with no session token' - ) + new ParseError(ParseError.SESSION_MISSING, 'Cannot upgrade a user with no session token') ); } options.sessionToken = token; const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'POST', - 'upgradeToRevocableSession', - {}, - options - ).then((result) => { + return RESTController.request('POST', 'upgradeToRevocableSession', {}, options).then(result => { const session = new ParseSession(); session._finishFetch(result); user._finishFetch({ sessionToken: session.getSessionToken() }); @@ -1249,23 +1194,13 @@ const DefaultController = { verifyPassword(username: string, password: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'GET', - 'verifyPassword', - { username, password }, - options - ); + return RESTController.request('GET', 'verifyPassword', { username, password }, options); }, requestEmailVerification(email: string, options: RequestOptions) { const RESTController = CoreManager.getRESTController(); - return RESTController.request( - 'POST', - 'verificationEmailRequest', - { email: email }, - options - ); - } + return RESTController.request('POST', 'verificationEmailRequest', { email: email }, options); + }, }; CoreManager.setUserController(DefaultController); diff --git a/src/Push.js b/src/Push.js index 6e7c5be98..dcfec330d 100644 --- a/src/Push.js +++ b/src/Push.js @@ -15,10 +15,10 @@ import ParseQuery from './ParseQuery'; import type { WhereClause } from './ParseQuery'; export type PushData = { - where?: WhereClause | ParseQuery; - push_time?: Date | string; - expiration_time?: Date | string; - expiration_interval?: number; + where?: WhereClause | ParseQuery, + push_time?: Date | string, + expiration_time?: Date | string, + expiration_interval?: number, }; /** @@ -66,9 +66,7 @@ export function send(data: PushData): Promise { } if (data.expiration_time && data.expiration_interval) { - throw new Error( - 'expiration_time and expiration_interval cannot both be set.' - ); + throw new Error('expiration_time and expiration_interval cannot both be set.'); } return CoreManager.getPushController().send(data); @@ -76,13 +74,10 @@ export function send(data: PushData): Promise { const DefaultController = { send(data: PushData) { - return CoreManager.getRESTController().request( - 'POST', - 'push', - data, - { useMasterKey: true } - ); - } -} + return CoreManager.getRESTController().request('POST', 'push', data, { + useMasterKey: true, + }); + }, +}; CoreManager.setPushController(DefaultController); diff --git a/src/RESTController.js b/src/RESTController.js index 0127d86d7..292cf9027 100644 --- a/src/RESTController.js +++ b/src/RESTController.js @@ -16,25 +16,25 @@ import ParseError from './ParseError'; import { resolvingPromise } from './promiseUtils'; export type RequestOptions = { - useMasterKey?: boolean; - sessionToken?: string; - installationId?: string; - returnStatus?: boolean; - batchSize?: number; - include?: any; - progress?: any; - context?: any; - usePost?: boolean; + useMasterKey?: boolean, + sessionToken?: string, + installationId?: string, + returnStatus?: boolean, + batchSize?: number, + include?: any, + progress?: any, + context?: any, + usePost?: boolean, }; export type FullOptions = { - success?: any; - error?: any; - useMasterKey?: boolean; - sessionToken?: string; - installationId?: string; - progress?: any; - usePost?: boolean; + success?: any, + error?: any, + useMasterKey?: boolean, + sessionToken?: string, + installationId?: string, + progress?: any, + usePost?: boolean, }; let XHR = null; @@ -49,15 +49,14 @@ if (process.env.PARSE_BUILD === 'weapp') { } let useXDomainRequest = false; -if (typeof XDomainRequest !== 'undefined' && - !('withCredentials' in new XMLHttpRequest())) { +if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in new XMLHttpRequest())) { useXDomainRequest = true; } function ajaxIE9(method: string, url: string, data: any, headers?: any, options?: FullOptions) { return new Promise((resolve, reject) => { const xdr = new XDomainRequest(); - xdr.onload = function() { + xdr.onload = function () { let response; try { response = JSON.parse(xdr.responseText); @@ -68,18 +67,18 @@ function ajaxIE9(method: string, url: string, data: any, headers?: any, options? resolve({ response }); } }; - xdr.onerror = xdr.ontimeout = function() { + xdr.onerror = xdr.ontimeout = function () { // Let's fake a real error message. const fakeResponse = { responseText: JSON.stringify({ code: ParseError.X_DOMAIN_REQUEST, - error: 'IE\'s XDomainRequest does not supply error info.' - }) + error: "IE's XDomainRequest does not supply error info.", + }), }; reject(fakeResponse); }; - xdr.onprogress = function() { - if(options && typeof options.progress === 'function') { + xdr.onprogress = function () { + if (options && typeof options.progress === 'function') { options.progress(xdr.responseText); } }; @@ -101,16 +100,14 @@ const RESTController = { const requestId = isIdempotent ? uuidv4() : ''; let attempts = 0; - const dispatch = function() { + const dispatch = function () { if (XHR == null) { - throw new Error( - 'Cannot make a request: No definition of XMLHttpRequest was found.' - ); + throw new Error('Cannot make a request: No definition of XMLHttpRequest was found.'); } let handled = false; const xhr = new XHR(); - xhr.onreadystatechange = function() { + xhr.onreadystatechange = function () { if (xhr.readyState !== 4 || handled || xhr._aborted) { return; } @@ -132,12 +129,11 @@ const RESTController = { if (response) { promise.resolve({ response, status: xhr.status, xhr }); } - } else if (xhr.status >= 500 || xhr.status === 0) { // retry on 5XX or node-xmlhttprequest error + } else if (xhr.status >= 500 || xhr.status === 0) { + // retry on 5XX or node-xmlhttprequest error if (++attempts < CoreManager.get('REQUEST_ATTEMPT_LIMIT')) { // Exponentially-growing random delay - const delay = Math.round( - Math.random() * 125 * Math.pow(2, attempts) - ); + const delay = Math.round(Math.random() * 125 * Math.pow(2, attempts)); setTimeout(dispatch, delay); } else if (xhr.status === 0) { promise.reject('Unable to connect to the Parse API'); @@ -151,18 +147,19 @@ const RESTController = { }; headers = headers || {}; - if (typeof(headers['Content-Type']) !== 'string') { + if (typeof headers['Content-Type'] !== 'string') { headers['Content-Type'] = 'text/plain'; // Avoid pre-flight } if (CoreManager.get('IS_NODE')) { - headers['User-Agent'] = 'Parse/' + CoreManager.get('VERSION') + - ' (NodeJS ' + process.versions.node + ')'; + headers['User-Agent'] = + 'Parse/' + CoreManager.get('VERSION') + ' (NodeJS ' + process.versions.node + ')'; } if (isIdempotent) { headers['X-Parse-Request-Id'] = requestId; } if (CoreManager.get('SERVER_AUTH_TYPE') && CoreManager.get('SERVER_AUTH_TOKEN')) { - headers['Authorization'] = CoreManager.get('SERVER_AUTH_TYPE') + ' ' + CoreManager.get('SERVER_AUTH_TOKEN'); + headers['Authorization'] = + CoreManager.get('SERVER_AUTH_TYPE') + ' ' + CoreManager.get('SERVER_AUTH_TOKEN'); } const customHeaders = CoreManager.get('REQUEST_HEADERS'); for (const key in customHeaders) { @@ -172,26 +169,21 @@ const RESTController = { function handleProgress(type, event) { if (options && typeof options.progress === 'function') { if (event.lengthComputable) { - options.progress( - event.loaded / event.total, - event.loaded, - event.total, - { type } - ); + options.progress(event.loaded / event.total, event.loaded, event.total, { type }); } else { options.progress(null, null, null, { type }); } } } - xhr.onprogress = (event) => { + xhr.onprogress = event => { handleProgress('download', event); }; if (xhr.upload) { - xhr.upload.onprogress = (event) => { + xhr.upload.onprogress = event => { handleProgress('upload', event); - } + }; } xhr.open(method, url, true); @@ -211,7 +203,7 @@ const RESTController = { if (options && typeof options.requestTask === 'function') { options.requestTask(xhr); } - } + }; dispatch(); return promise; @@ -276,34 +268,39 @@ const RESTController = { installationIdPromise = installationController.currentInstallationId(); } - return installationIdPromise.then((iid) => { - payload._InstallationId = iid; - const userController = CoreManager.getUserController(); - if (options && typeof options.sessionToken === 'string') { - return Promise.resolve(options.sessionToken); - } else if (userController) { - return userController.currentUserAsync().then((user) => { - if (user) { - return Promise.resolve(user.getSessionToken()); - } - return Promise.resolve(null); - }); - } - return Promise.resolve(null); - }).then((token) => { - if (token) { - payload._SessionToken = token; - } - - const payloadString = JSON.stringify(payload); - return RESTController.ajax(method, url, payloadString, {}, options).then(({ response, status })=>{ - if (options.returnStatus) { - return { ...response, _status: status }; - } else { - return response; + return installationIdPromise + .then(iid => { + payload._InstallationId = iid; + const userController = CoreManager.getUserController(); + if (options && typeof options.sessionToken === 'string') { + return Promise.resolve(options.sessionToken); + } else if (userController) { + return userController.currentUserAsync().then(user => { + if (user) { + return Promise.resolve(user.getSessionToken()); + } + return Promise.resolve(null); + }); + } + return Promise.resolve(null); + }) + .then(token => { + if (token) { + payload._SessionToken = token; } - }); - }).catch(RESTController.handleError); + + const payloadString = JSON.stringify(payload); + return RESTController.ajax(method, url, payloadString, {}, options).then( + ({ response, status }) => { + if (options.returnStatus) { + return { ...response, _status: status }; + } else { + return response; + } + } + ); + }) + .catch(RESTController.handleError); }, handleError(response) { @@ -318,8 +315,7 @@ const RESTController = { // If we fail to parse the error text, that's okay. error = new ParseError( ParseError.INVALID_JSON, - 'Received an error with invalid JSON from Parse: ' + - response.responseText + 'Received an error with invalid JSON from Parse: ' + response.responseText ); } } else { @@ -338,7 +334,7 @@ const RESTController = { _getXHR() { return XHR; - } -} + }, +}; module.exports = RESTController; diff --git a/src/SingleInstanceStateController.js b/src/SingleInstanceStateController.js index 112cd74f4..5ef86c442 100644 --- a/src/SingleInstanceStateController.js +++ b/src/SingleInstanceStateController.js @@ -15,14 +15,14 @@ import type { Op } from './ParseOp'; import type { AttributeMap, ObjectCache, OpsMap, State } from './ObjectStateMutations'; type ObjectIdentifier = { - className: string; - id: string + className: string, + id: string, }; let objectState: { [className: string]: { - [id: string]: State - } + [id: string]: State, + }, } = {}; export function getState(obj: ObjectIdentifier): ?State { @@ -109,7 +109,13 @@ export function getObjectCache(obj: ObjectIdentifier): ObjectCache { export function estimateAttribute(obj: ObjectIdentifier, attr: string): mixed { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttribute(serverData, pendingOps, obj.className, obj.id, attr); + return ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + obj.className, + obj.id, + attr + ); } export function estimateAttributes(obj: ObjectIdentifier): AttributeMap { @@ -132,6 +138,6 @@ export function clearAllState() { objectState = {}; } -export function duplicateState(source: {id: string}, dest: {id: string}) { +export function duplicateState(source: { id: string }, dest: { id: string }) { dest.id = source.id; } diff --git a/src/Socket.weapp.js b/src/Socket.weapp.js index bd56b8151..35affd6f3 100644 --- a/src/Socket.weapp.js +++ b/src/Socket.weapp.js @@ -1,15 +1,15 @@ module.exports = class SocketWeapp { constructor(serverURL) { - this.onopen = () => {} - this.onmessage = () => {} - this.onclose = () => {} - this.onerror = () => {} + this.onopen = () => {}; + this.onmessage = () => {}; + this.onclose = () => {}; + this.onerror = () => {}; wx.onSocketOpen(() => { this.onopen(); - }) + }); - wx.onSocketMessage((msg) => { + wx.onSocketMessage(msg => { this.onmessage(msg); }); @@ -17,7 +17,7 @@ module.exports = class SocketWeapp { this.onclose(); }); - wx.onSocketError((error) => { + wx.onSocketError(error => { this.onerror(error); }); @@ -33,4 +33,4 @@ module.exports = class SocketWeapp { close() { wx.closeSocket(); } -} +}; diff --git a/src/Storage.js b/src/Storage.js index 0388ca698..0f2806145 100644 --- a/src/Storage.js +++ b/src/Storage.js @@ -20,9 +20,7 @@ const Storage = { getItem(path: string): ?string { const controller = CoreManager.getStorageController(); if (controller.async === 1) { - throw new Error( - 'Synchronous storage is not supported by the current storage controller' - ); + throw new Error('Synchronous storage is not supported by the current storage controller'); } return controller.getItem(path); }, @@ -38,9 +36,7 @@ const Storage = { setItem(path: string, value: string): void { const controller = CoreManager.getStorageController(); if (controller.async === 1) { - throw new Error( - 'Synchronous storage is not supported by the current storage controller' - ); + throw new Error('Synchronous storage is not supported by the current storage controller'); } return controller.setItem(path, value); }, @@ -56,9 +52,7 @@ const Storage = { removeItem(path: string): void { const controller = CoreManager.getStorageController(); if (controller.async === 1) { - throw new Error( - 'Synchronous storage is not supported by the current storage controller' - ); + throw new Error('Synchronous storage is not supported by the current storage controller'); } return controller.removeItem(path); }, @@ -74,9 +68,7 @@ const Storage = { getAllKeys(): Array { const controller = CoreManager.getStorageController(); if (controller.async === 1) { - throw new Error( - 'Synchronous storage is not supported by the current storage controller' - ); + throw new Error('Synchronous storage is not supported by the current storage controller'); } return controller.getAllKeys(); }, @@ -107,7 +99,7 @@ const Storage = { if (controller.hasOwnProperty('clear')) { controller.clear(); } - } + }, }; module.exports = Storage; diff --git a/src/StorageController.browser.js b/src/StorageController.browser.js index 56d40ef66..e8e5d6497 100644 --- a/src/StorageController.browser.js +++ b/src/StorageController.browser.js @@ -41,7 +41,7 @@ const StorageController = { clear() { localStorage.clear(); - } + }, }; module.exports = StorageController; diff --git a/src/StorageController.default.js b/src/StorageController.default.js index 105dd0cc4..c939b6e74 100644 --- a/src/StorageController.default.js +++ b/src/StorageController.default.js @@ -40,7 +40,7 @@ const StorageController = { delete memMap[key]; } } - } + }, }; module.exports = StorageController; diff --git a/src/StorageController.react-native.js b/src/StorageController.react-native.js index a4012a5e4..b6b8443c2 100644 --- a/src/StorageController.react-native.js +++ b/src/StorageController.react-native.js @@ -21,7 +21,7 @@ const StorageController = { getItemAsync(path: string): Promise { return new Promise((resolve, reject) => { - this.getAsyncStorage().getItem(path, function(err, value) { + this.getAsyncStorage().getItem(path, function (err, value) { if (err) { reject(err); } else { @@ -33,7 +33,7 @@ const StorageController = { setItemAsync(path: string, value: string): Promise { return new Promise((resolve, reject) => { - this.getAsyncStorage().setItem(path, value, function(err, value) { + this.getAsyncStorage().setItem(path, value, function (err, value) { if (err) { reject(err); } else { @@ -45,7 +45,7 @@ const StorageController = { removeItemAsync(path: string): Promise { return new Promise((resolve, reject) => { - this.getAsyncStorage().removeItem(path, function(err) { + this.getAsyncStorage().removeItem(path, function (err) { if (err) { reject(err); } else { @@ -57,7 +57,7 @@ const StorageController = { getAllKeysAsync(): Promise { return new Promise((resolve, reject) => { - this.getAsyncStorage().getAllKeys(function(err, keys) { + this.getAsyncStorage().getAllKeys(function (err, keys) { if (err) { reject(err); } else { @@ -69,7 +69,7 @@ const StorageController = { multiGet(keys: Array): Promise>> { return new Promise((resolve, reject) => { - this.getAsyncStorage().multiGet(keys, function(err, result) { + this.getAsyncStorage().multiGet(keys, function (err, result) { if (err) { reject(err); } else { @@ -81,7 +81,7 @@ const StorageController = { multiRemove(keys: Array): Promise { return new Promise((resolve, reject) => { - this.getAsyncStorage().multiRemove(keys, function(err) { + this.getAsyncStorage().multiRemove(keys, function (err) { if (err) { reject(err); } else { @@ -93,7 +93,7 @@ const StorageController = { clear() { return this.getAsyncStorage().clear(); - } + }, }; module.exports = StorageController; diff --git a/src/StorageController.weapp.js b/src/StorageController.weapp.js index 283f1ee59..b72e05c67 100644 --- a/src/StorageController.weapp.js +++ b/src/StorageController.weapp.js @@ -36,7 +36,7 @@ const StorageController = { clear() { wx.clearStorageSync(); - } + }, }; module.exports = StorageController; diff --git a/src/TaskQueue.js b/src/TaskQueue.js index 04b3a257b..58d4df297 100644 --- a/src/TaskQueue.js +++ b/src/TaskQueue.js @@ -11,8 +11,8 @@ import { resolvingPromise } from './promiseUtils'; type Task = { - task: () => Promise; - _completion: Promise + task: () => Promise, + _completion: Promise, }; class TaskQueue { @@ -26,16 +26,19 @@ class TaskQueue { const taskComplete = new resolvingPromise(); this.queue.push({ task: task, - _completion: taskComplete + _completion: taskComplete, }); if (this.queue.length === 1) { - task().then(() => { - this._dequeue(); - taskComplete.resolve(); - }, (error) => { - this._dequeue(); - taskComplete.reject(error); - }); + task().then( + () => { + this._dequeue(); + taskComplete.resolve(); + }, + error => { + this._dequeue(); + taskComplete.reject(error); + } + ); } return taskComplete; } @@ -44,13 +47,16 @@ class TaskQueue { this.queue.shift(); if (this.queue.length) { const next = this.queue[0]; - next.task().then(() => { - this._dequeue(); - next._completion.resolve(); - }, (error) => { - this._dequeue(); - next._completion.reject(error); - }); + next.task().then( + () => { + this._dequeue(); + next._completion.resolve(); + }, + error => { + this._dequeue(); + next._completion.reject(error); + } + ); } } } diff --git a/src/UniqueInstanceStateController.js b/src/UniqueInstanceStateController.js index 43e896938..8ecbcee9b 100644 --- a/src/UniqueInstanceStateController.js +++ b/src/UniqueInstanceStateController.js @@ -34,7 +34,7 @@ export function initializeState(obj: ParseObject, initial?: State): State { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }; } state = initial; @@ -103,7 +103,13 @@ export function getObjectCache(obj: ParseObject): ObjectCache { export function estimateAttribute(obj: ParseObject, attr: string): mixed { const serverData = getServerData(obj); const pendingOps = getPendingOps(obj); - return ObjectStateMutations.estimateAttribute(serverData, pendingOps, obj.className, obj.id, attr); + return ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + obj.className, + obj.id, + attr + ); } export function estimateAttributes(obj: ParseObject): AttributeMap { diff --git a/src/Xhr.weapp.js b/src/Xhr.weapp.js index ec6c20495..cb9f90121 100644 --- a/src/Xhr.weapp.js +++ b/src/Xhr.weapp.js @@ -24,8 +24,8 @@ module.exports = class XhrWeapp { getAllResponseHeaders() { let header = ''; - for(const key in this.responseHeader){ - header += key + ':' + this.getResponseHeader(key) + '\r\n' + for (const key in this.responseHeader) { + header += key + ':' + this.getResponseHeader(key) + '\r\n'; } return header; } @@ -61,7 +61,7 @@ module.exports = class XhrWeapp { data: data, header: this.header, responseType: this.responseType, - success: (res) => { + success: res => { this.status = res.statusCode; this.response = res.data; this.responseHeader = res.header; @@ -69,14 +69,14 @@ module.exports = class XhrWeapp { this.requestTask = null; this.onreadystatechange(); }, - fail: (err) => { + fail: err => { this.requestTask = null; this.onerror(err); - } + }, }); - this.requestTask.onProgressUpdate((res) => { + this.requestTask.onProgressUpdate(res => { const event = { - lengthComputable: (res.totalBytesExpectedToWrite !== 0), + lengthComputable: res.totalBytesExpectedToWrite !== 0, loaded: res.totalBytesWritten, total: res.totalBytesExpectedToWrite, }; diff --git a/src/__tests__/Analytics-test.js b/src/__tests__/Analytics-test.js index 3509a78eb..8c1845c1c 100644 --- a/src/__tests__/Analytics-test.js +++ b/src/__tests__/Analytics-test.js @@ -23,39 +23,38 @@ describe('Analytics', () => { }); it('throws when no event name is provided', () => { - expect(Analytics.track) - .toThrow('A name for the custom event must be provided'); + expect(Analytics.track).toThrow('A name for the custom event must be provided'); - expect(Analytics.track.bind(null, '')) - .toThrow('A name for the custom event must be provided'); + expect(Analytics.track.bind(null, '')).toThrow('A name for the custom event must be provided'); }); it('trims whitespace from event names', () => { Analytics.track(' before', {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[0]) - .toEqual(['before', {}]); + expect(CoreManager.getAnalyticsController().track.mock.calls[0]).toEqual(['before', {}]); Analytics.track('after ', {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[1]) - .toEqual(['after', {}]); + expect(CoreManager.getAnalyticsController().track.mock.calls[1]).toEqual(['after', {}]); Analytics.track(' both ', {}); - expect(CoreManager.getAnalyticsController().track.mock.calls[2]) - .toEqual(['both', {}]); + expect(CoreManager.getAnalyticsController().track.mock.calls[2]).toEqual(['both', {}]); }); it('passes along event names and dimensions', () => { Analytics.track('myEvent', { value: 'a' }); - expect(CoreManager.getAnalyticsController().track.mock.calls[0]) - .toEqual(['myEvent', { value: 'a' }]); + expect(CoreManager.getAnalyticsController().track.mock.calls[0]).toEqual([ + 'myEvent', + { value: 'a' }, + ]); }); it('throws when invalid dimensions are provided', () => { - expect(Analytics.track.bind(null, 'event', { number: 12 })) - .toThrow('track() dimensions expects keys and values of type "string".'); + expect(Analytics.track.bind(null, 'event', { number: 12 })).toThrow( + 'track() dimensions expects keys and values of type "string".' + ); - expect(Analytics.track.bind(null, 'event', { 'null': null })) - .toThrow('track() dimensions expects keys and values of type "string".'); + expect(Analytics.track.bind(null, 'event', { null: null })).toThrow( + 'track() dimensions expects keys and values of type "string".' + ); }); }); @@ -63,10 +62,12 @@ describe('AnalyticsController', () => { beforeEach(() => { CoreManager.setAnalyticsController(defaultController); const request = jest.fn(); - request.mockReturnValue(Promise.resolve({ - success: true, - result: {} - })); + request.mockReturnValue( + Promise.resolve({ + success: true, + result: {}, + }) + ); const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); }); @@ -74,11 +75,10 @@ describe('AnalyticsController', () => { it('passes dimensions along to the appropriate endpoint', () => { Analytics.track('click', { x: '12', y: '40' }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual([ - 'POST', - 'events/click', - { dimensions: { x: '12', y: '40'} } - ]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'POST', + 'events/click', + { dimensions: { x: '12', y: '40' } }, + ]); }); }); diff --git a/src/__tests__/AnonymousUtils-test.js b/src/__tests__/AnonymousUtils-test.js index 2ef1abfd1..f64d92bb1 100644 --- a/src/__tests__/AnonymousUtils-test.js +++ b/src/__tests__/AnonymousUtils-test.js @@ -10,7 +10,7 @@ jest.dontMock('../AnonymousUtils'); class MockUser { - constructor () { + constructor() { this.className = '_User'; this.attributes = {}; } @@ -45,11 +45,7 @@ const AnonymousUtils = require('../AnonymousUtils').default; describe('AnonymousUtils', () => { beforeEach(() => { jest.clearAllMocks(); - jest.spyOn( - AnonymousUtils, - '_getAuthProvider' - ) - .mockImplementation(() => mockProvider); + jest.spyOn(AnonymousUtils, '_getAuthProvider').mockImplementation(() => mockProvider); }); it('can register provider', () => { @@ -82,7 +78,11 @@ describe('AnonymousUtils', () => { jest.spyOn(MockUser, 'logInWith'); AnonymousUtils.logIn(); expect(MockUser.logInWith).toHaveBeenCalledTimes(1); - expect(MockUser.logInWith).toHaveBeenCalledWith('anonymous', mockProvider.getAuthData(), undefined); + expect(MockUser.logInWith).toHaveBeenCalledWith( + 'anonymous', + mockProvider.getAuthData(), + undefined + ); expect(AnonymousUtils._getAuthProvider).toHaveBeenCalledTimes(1); }); }); diff --git a/src/__tests__/Cloud-test.js b/src/__tests__/Cloud-test.js index 14d5d42b4..370e6393e 100644 --- a/src/__tests__/Cloud-test.js +++ b/src/__tests__/Cloud-test.js @@ -25,93 +25,108 @@ describe('Cloud', () => { const run = jest.fn(); const getJobsData = jest.fn(); const startJob = jest.fn(); - run.mockReturnValue(Promise.resolve({ - result: {} - })); - getJobsData.mockReturnValue(Promise.resolve({ - result: {} - })); - startJob.mockReturnValue(Promise.resolve({ - result: {} - })); + run.mockReturnValue( + Promise.resolve({ + result: {}, + }) + ); + getJobsData.mockReturnValue( + Promise.resolve({ + result: {}, + }) + ); + startJob.mockReturnValue( + Promise.resolve({ + result: {}, + }) + ); CoreManager.setCloudController({ run, getJobsData, startJob }); }); it('run throws with an invalid function name', () => { - expect(Cloud.run) - .toThrow('Cloud function name must be a string.'); + expect(Cloud.run).toThrow('Cloud function name must be a string.'); - expect(Cloud.run.bind(null, '')) - .toThrow('Cloud function name must be a string.'); + expect(Cloud.run.bind(null, '')).toThrow('Cloud function name must be a string.'); - expect(Cloud.run.bind(null, {})) - .toThrow('Cloud function name must be a string.'); + expect(Cloud.run.bind(null, {})).toThrow('Cloud function name must be a string.'); }); it('run passes function name and data along', () => { Cloud.run('myfunction', {}); - expect(CoreManager.getCloudController().run.mock.calls[0]) - .toEqual(['myfunction', {}, {}]); + expect(CoreManager.getCloudController().run.mock.calls[0]).toEqual(['myfunction', {}, {}]); }); it('run passes options', () => { Cloud.run('myfunction', {}, { useMasterKey: false }); - expect(CoreManager.getCloudController().run.mock.calls[0]) - .toEqual(['myfunction', {}, {}]); + expect(CoreManager.getCloudController().run.mock.calls[0]).toEqual(['myfunction', {}, {}]); Cloud.run('myfunction', {}, { useMasterKey: true }); - expect(CoreManager.getCloudController().run.mock.calls[1]) - .toEqual(['myfunction', {}, { useMasterKey: true }]); + expect(CoreManager.getCloudController().run.mock.calls[1]).toEqual([ + 'myfunction', + {}, + { useMasterKey: true }, + ]); Cloud.run('myfunction', {}, { sessionToken: 'asdf1234' }); - expect(CoreManager.getCloudController().run.mock.calls[2]) - .toEqual(['myfunction', {}, { sessionToken: 'asdf1234' }]); + expect(CoreManager.getCloudController().run.mock.calls[2]).toEqual([ + 'myfunction', + {}, + { sessionToken: 'asdf1234' }, + ]); Cloud.run('myfunction', {}, { useMasterKey: true, sessionToken: 'asdf1234' }); - expect(CoreManager.getCloudController().run.mock.calls[3]) - .toEqual(['myfunction', {}, { useMasterKey: true, sessionToken: 'asdf1234' }]); + expect(CoreManager.getCloudController().run.mock.calls[3]).toEqual([ + 'myfunction', + {}, + { useMasterKey: true, sessionToken: 'asdf1234' }, + ]); }); it('startJob throws with an invalid job name', () => { - expect(Cloud.startJob) - .toThrow('Cloud job name must be a string.'); + expect(Cloud.startJob).toThrow('Cloud job name must be a string.'); - expect(Cloud.startJob.bind(null, '')) - .toThrow('Cloud job name must be a string.'); + expect(Cloud.startJob.bind(null, '')).toThrow('Cloud job name must be a string.'); - expect(Cloud.startJob.bind(null, {})) - .toThrow('Cloud job name must be a string.'); + expect(Cloud.startJob.bind(null, {})).toThrow('Cloud job name must be a string.'); }); it('startJob passes function name and data along', () => { Cloud.startJob('myJob', {}); - expect(CoreManager.getCloudController().startJob.mock.calls[0]) - .toEqual(['myJob', {}, { useMasterKey: true }]); + expect(CoreManager.getCloudController().startJob.mock.calls[0]).toEqual([ + 'myJob', + {}, + { useMasterKey: true }, + ]); }); it('startJob passes options', () => { Cloud.startJob('myJob', {}, { useMasterKey: true }); - expect(CoreManager.getCloudController().startJob.mock.calls[0]) - .toEqual(['myJob', {}, { useMasterKey: true }]); + expect(CoreManager.getCloudController().startJob.mock.calls[0]).toEqual([ + 'myJob', + {}, + { useMasterKey: true }, + ]); }); it('getJobsData passes options', () => { Cloud.getJobsData(); - expect(CoreManager.getCloudController().getJobsData.mock.calls[0]) - .toEqual([{ useMasterKey: true }]); + expect(CoreManager.getCloudController().getJobsData.mock.calls[0]).toEqual([ + { useMasterKey: true }, + ]); Cloud.getJobsData({ useMasterKey: true }); - expect(CoreManager.getCloudController().getJobsData.mock.calls[0]) - .toEqual([{ useMasterKey: true }]); + expect(CoreManager.getCloudController().getJobsData.mock.calls[0]).toEqual([ + { useMasterKey: true }, + ]); }); }); @@ -119,53 +134,75 @@ describe('CloudController', () => { beforeEach(() => { CoreManager.setCloudController(defaultController); const request = jest.fn(); - request.mockReturnValue(Promise.resolve({ - success: true, - result: {} - })); + request.mockReturnValue( + Promise.resolve({ + success: true, + result: {}, + }) + ); const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); }); it('run passes encoded requests', () => { - Cloud.run('myfunction', { value: 12, when: new Date(Date.UTC(2015,0,1)) }); + Cloud.run('myfunction', { + value: 12, + when: new Date(Date.UTC(2015, 0, 1)), + }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['POST', 'functions/myfunction', { - value: 12, when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z'} - }, { }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'POST', + 'functions/myfunction', + { + value: 12, + when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z' }, + }, + {}, + ]); }); it('run passes options', () => { Cloud.run('myfunction', { value: 12 }, { useMasterKey: true }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['POST', 'functions/myfunction', { - value: 12 - }, { useMasterKey: true }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'POST', + 'functions/myfunction', + { + value: 12, + }, + { useMasterKey: true }, + ]); Cloud.run('myfunction', { value: 12 }, { sessionToken: 'asdf1234' }); - expect(CoreManager.getRESTController().request.mock.calls[1]) - .toEqual(['POST', 'functions/myfunction', { - value: 12 - }, { sessionToken: 'asdf1234' }]); + expect(CoreManager.getRESTController().request.mock.calls[1]).toEqual([ + 'POST', + 'functions/myfunction', + { + value: 12, + }, + { sessionToken: 'asdf1234' }, + ]); }); - it('run invalid response', (done) => { + it('run invalid response', done => { const request = jest.fn(); - request.mockReturnValue(Promise.resolve({ - success: false - })); + request.mockReturnValue( + Promise.resolve({ + success: false, + }) + ); const ajax = jest.fn(); CoreManager.setRESTController({ request: request, ajax: ajax }); - Cloud.run('myfunction').then(null).catch(() => { - done(); - }); + Cloud.run('myfunction') + .then(null) + .catch(() => { + done(); + }); }); - it('run undefined response', (done) => { + it('run undefined response', done => { const request = jest.fn(); request.mockReturnValue(Promise.resolve(undefined)); @@ -178,35 +215,55 @@ describe('CloudController', () => { }); it('startJob passes encoded requests', () => { - Cloud.startJob('myJob', { value: 12, when: new Date(Date.UTC(2015,0,1)) }); + Cloud.startJob('myJob', { + value: 12, + when: new Date(Date.UTC(2015, 0, 1)), + }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['POST', 'jobs/myJob', { - value: 12, when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z'} - }, { useMasterKey: true }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'POST', + 'jobs/myJob', + { + value: 12, + when: { __type: 'Date', iso: '2015-01-01T00:00:00.000Z' }, + }, + { useMasterKey: true }, + ]); }); it('startJob passes options', () => { Cloud.startJob('myJob', { value: 12 }, { useMasterKey: true }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['POST', 'jobs/myJob', { - value: 12 - }, { useMasterKey: true }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'POST', + 'jobs/myJob', + { + value: 12, + }, + { useMasterKey: true }, + ]); }); it('getJobsData passes no options', () => { Cloud.getJobsData(); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['GET', 'cloud_code/jobs/data', null, { useMasterKey: true }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'GET', + 'cloud_code/jobs/data', + null, + { useMasterKey: true }, + ]); }); it('getJobsData passes options', () => { Cloud.getJobsData({ useMasterKey: true }); - expect(CoreManager.getRESTController().request.mock.calls[0]) - .toEqual(['GET', 'cloud_code/jobs/data', null, { useMasterKey: true }]); + expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ + 'GET', + 'cloud_code/jobs/data', + null, + { useMasterKey: true }, + ]); }); it('accepts context on cloud function call', async () => { @@ -220,7 +277,7 @@ describe('CloudController', () => { const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'request'); // Save object - const context = {a: "a"}; + const context = { a: 'a' }; await Cloud.run('myfunction', {}, { context: context }); // Validate expect(controller.request.mock.calls[0][3].context).toEqual(context); @@ -228,13 +285,15 @@ describe('CloudController', () => { it('can get job status', async () => { const request = jest.fn(); - request.mockReturnValue(Promise.resolve({ - results: [{ className: '_JobStatus', objectId: 'jobId1234' }], - })); + request.mockReturnValue( + Promise.resolve({ + results: [{ className: '_JobStatus', objectId: 'jobId1234' }], + }) + ); CoreManager.setRESTController({ request: request, ajax: jest.fn() }); await Cloud.getJobStatus('jobId1234'); - const [ method, path, data, options] = request.mock.calls[0]; + const [method, path, data, options] = request.mock.calls[0]; expect(method).toBe('GET'); expect(path).toBe('classes/_JobStatus'); expect(data).toEqual({ diff --git a/src/__tests__/CoreManager-test.js b/src/__tests__/CoreManager-test.js index 81bb2691a..4b4c747ac 100644 --- a/src/__tests__/CoreManager-test.js +++ b/src/__tests__/CoreManager-test.js @@ -37,14 +37,16 @@ describe('CoreManager', () => { 'AnalyticsController must implement track()' ); - expect(CoreManager.setAnalyticsController.bind(null, { - track: function() {} - })).not.toThrow(); + expect( + CoreManager.setAnalyticsController.bind(null, { + track: function () {}, + }) + ).not.toThrow(); }); it('can set and get AnalyticsController', () => { const controller = { - track: function() {} + track: function () {}, }; CoreManager.setAnalyticsController(controller); @@ -56,20 +58,22 @@ describe('CoreManager', () => { 'CloudController must implement run()' ); - expect(CoreManager.setCloudController.bind(null, { - run: function() {}, - getJobsData: function() {}, - startJob: function() {}, - getJobStatus: function() {} - })).not.toThrow(); + expect( + CoreManager.setCloudController.bind(null, { + run: function () {}, + getJobsData: function () {}, + startJob: function () {}, + getJobStatus: function () {}, + }) + ).not.toThrow(); }); it('can set and get CloudController', () => { const controller = { - run: function() {}, - getJobsData: function() {}, - startJob: function() {}, - getJobStatus: function() {} + run: function () {}, + getJobsData: function () {}, + startJob: function () {}, + getJobStatus: function () {}, }; CoreManager.setCloudController(controller); @@ -81,22 +85,26 @@ describe('CoreManager', () => { 'ConfigController must implement current()' ); - expect(CoreManager.setConfigController.bind(null, { - current: function() {} - })).toThrow('ConfigController must implement get()'); - - expect(CoreManager.setConfigController.bind(null, { - current: function() {}, - get: function() {}, - save : function() {} - })).not.toThrow(); + expect( + CoreManager.setConfigController.bind(null, { + current: function () {}, + }) + ).toThrow('ConfigController must implement get()'); + + expect( + CoreManager.setConfigController.bind(null, { + current: function () {}, + get: function () {}, + save: function () {}, + }) + ).not.toThrow(); }); it('can set and get ConfigController', () => { const controller = { - current: function() {}, - get: function() {}, - save : function() {} + current: function () {}, + get: function () {}, + save: function () {}, }; CoreManager.setConfigController(controller); @@ -108,20 +116,24 @@ describe('CoreManager', () => { 'FileController must implement saveFile()' ); - expect(CoreManager.setFileController.bind(null, { - saveFile: function() {} - })).toThrow('FileController must implement saveBase64()'); - - expect(CoreManager.setFileController.bind(null, { - saveFile: function() {}, - saveBase64: function() {} - })).not.toThrow(); + expect( + CoreManager.setFileController.bind(null, { + saveFile: function () {}, + }) + ).toThrow('FileController must implement saveBase64()'); + + expect( + CoreManager.setFileController.bind(null, { + saveFile: function () {}, + saveBase64: function () {}, + }) + ).not.toThrow(); }); it('can set and get FileController', () => { const controller = { - saveFile: function() {}, - saveBase64: function() {} + saveFile: function () {}, + saveBase64: function () {}, }; CoreManager.setFileController(controller); @@ -133,14 +145,16 @@ describe('CoreManager', () => { 'InstallationController must implement currentInstallationId()' ); - expect(CoreManager.setInstallationController.bind(null, { - currentInstallationId: function() {} - })).not.toThrow(); + expect( + CoreManager.setInstallationController.bind(null, { + currentInstallationId: function () {}, + }) + ).not.toThrow(); }); it('can set and get InstallationController', () => { const controller = { - currentInstallationId: function() {} + currentInstallationId: function () {}, }; CoreManager.setInstallationController(controller); @@ -152,14 +166,16 @@ describe('CoreManager', () => { 'PushController must implement send()' ); - expect(CoreManager.setPushController.bind(null, { - send: function() {} - })).not.toThrow(); + expect( + CoreManager.setPushController.bind(null, { + send: function () {}, + }) + ).not.toThrow(); }); it('can set and get PushController', () => { const controller = { - send: function() {} + send: function () {}, }; CoreManager.setPushController(controller); @@ -171,27 +187,33 @@ describe('CoreManager', () => { 'ObjectController must implement save()' ); - expect(CoreManager.setObjectController.bind(null, { - save: function() {} - })).toThrow('ObjectController must implement fetch()'); - - expect(CoreManager.setObjectController.bind(null, { - save: function() {}, - fetch: function() {} - })).toThrow('ObjectController must implement destroy()'); - - expect(CoreManager.setObjectController.bind(null, { - save: function() {}, - fetch: function() {}, - destroy: function() {} - })).not.toThrow(); + expect( + CoreManager.setObjectController.bind(null, { + save: function () {}, + }) + ).toThrow('ObjectController must implement fetch()'); + + expect( + CoreManager.setObjectController.bind(null, { + save: function () {}, + fetch: function () {}, + }) + ).toThrow('ObjectController must implement destroy()'); + + expect( + CoreManager.setObjectController.bind(null, { + save: function () {}, + fetch: function () {}, + destroy: function () {}, + }) + ).not.toThrow(); }); it('can set and get ObjectController', () => { const controller = { - save: function() {}, - fetch: function() {}, - destroy: function() {} + save: function () {}, + fetch: function () {}, + destroy: function () {}, }; CoreManager.setObjectController(controller); @@ -200,22 +222,22 @@ describe('CoreManager', () => { it('can set and get ObjectStateController', () => { const controller = { - getState: function() {}, - initializeState: function() {}, - removeState: function() {}, - getServerData: function() {}, - setServerData: function() {}, - getPendingOps: function() {}, - setPendingOp: function() {}, - pushPendingState: function() {}, - popPendingState: function() {}, - mergeFirstPendingState: function() {}, - getObjectCache: function() {}, - estimateAttribute: function() {}, - estimateAttributes: function() {}, - commitServerChanges: function() {}, - enqueueTask: function() {}, - clearAllState: function() {}, + getState: function () {}, + initializeState: function () {}, + removeState: function () {}, + getServerData: function () {}, + setServerData: function () {}, + getPendingOps: function () {}, + setPendingOp: function () {}, + pushPendingState: function () {}, + popPendingState: function () {}, + mergeFirstPendingState: function () {}, + getObjectCache: function () {}, + estimateAttribute: function () {}, + estimateAttributes: function () {}, + commitServerChanges: function () {}, + enqueueTask: function () {}, + clearAllState: function () {}, }; CoreManager.setObjectStateController(controller); @@ -227,16 +249,18 @@ describe('CoreManager', () => { 'QueryController must implement find()' ); - expect(CoreManager.setQueryController.bind(null, { - find: function() {}, - aggregate: function() {} - })).not.toThrow(); + expect( + CoreManager.setQueryController.bind(null, { + find: function () {}, + aggregate: function () {}, + }) + ).not.toThrow(); }); it('can set and get QueryController', () => { const controller = { - find: function() {}, - aggregate: function() {} + find: function () {}, + aggregate: function () {}, }; CoreManager.setQueryController(controller); @@ -248,20 +272,24 @@ describe('CoreManager', () => { 'RESTController must implement request()' ); - expect(CoreManager.setRESTController.bind(null, { - request: function() {} - })).toThrow('RESTController must implement ajax()'); - - expect(CoreManager.setRESTController.bind(null, { - request: function() {}, - ajax: function() {} - })).not.toThrow(); + expect( + CoreManager.setRESTController.bind(null, { + request: function () {}, + }) + ).toThrow('RESTController must implement ajax()'); + + expect( + CoreManager.setRESTController.bind(null, { + request: function () {}, + ajax: function () {}, + }) + ).not.toThrow(); }); it('can set and get RESTController', () => { const controller = { - request: function() {}, - ajax: function() {} + request: function () {}, + ajax: function () {}, }; CoreManager.setRESTController(controller); @@ -273,56 +301,68 @@ describe('CoreManager', () => { 'A synchronous StorageController must implement getItem()' ); - expect(CoreManager.setStorageController.bind(null, { - async: 0, - getItem: function() {} - })).toThrow('A synchronous StorageController must implement setItem()'); - - expect(CoreManager.setStorageController.bind(null, { - async: 0, - getItem: function() {}, - setItem: function() {} - })).toThrow('A synchronous StorageController must implement removeItem()'); - - expect(CoreManager.setStorageController.bind(null, { - async: 0, - getItem: function() {}, - setItem: function() {}, - removeItem: function() {}, - getAllKeys: function() {} - })).not.toThrow(); + expect( + CoreManager.setStorageController.bind(null, { + async: 0, + getItem: function () {}, + }) + ).toThrow('A synchronous StorageController must implement setItem()'); + + expect( + CoreManager.setStorageController.bind(null, { + async: 0, + getItem: function () {}, + setItem: function () {}, + }) + ).toThrow('A synchronous StorageController must implement removeItem()'); + + expect( + CoreManager.setStorageController.bind(null, { + async: 0, + getItem: function () {}, + setItem: function () {}, + removeItem: function () {}, + getAllKeys: function () {}, + }) + ).not.toThrow(); expect(CoreManager.setStorageController.bind(null, { async: 1 })).toThrow( 'An async StorageController must implement getItemAsync()' ); - expect(CoreManager.setStorageController.bind(null, { - async: 1, - getItemAsync: function() {} - })).toThrow('An async StorageController must implement setItemAsync()'); - - expect(CoreManager.setStorageController.bind(null, { - async: 1, - getItemAsync: function() {}, - setItemAsync: function() {} - })).toThrow('An async StorageController must implement removeItemAsync()'); - - expect(CoreManager.setStorageController.bind(null, { - async: 1, - getItemAsync: function() {}, - setItemAsync: function() {}, - removeItemAsync: function() {}, - getAllKeysAsync: function() {} - })).not.toThrow(); + expect( + CoreManager.setStorageController.bind(null, { + async: 1, + getItemAsync: function () {}, + }) + ).toThrow('An async StorageController must implement setItemAsync()'); + + expect( + CoreManager.setStorageController.bind(null, { + async: 1, + getItemAsync: function () {}, + setItemAsync: function () {}, + }) + ).toThrow('An async StorageController must implement removeItemAsync()'); + + expect( + CoreManager.setStorageController.bind(null, { + async: 1, + getItemAsync: function () {}, + setItemAsync: function () {}, + removeItemAsync: function () {}, + getAllKeysAsync: function () {}, + }) + ).not.toThrow(); }); it('can set and get StorageController', () => { const controller = { async: 0, - getItem: function() {}, - setItem: function() {}, - removeItem: function() {}, - getAllKeys: function() {} + getItem: function () {}, + setItem: function () {}, + removeItem: function () {}, + getAllKeys: function () {}, }; CoreManager.setStorageController(controller); @@ -334,24 +374,26 @@ describe('CoreManager', () => { 'SchemaController must implement get()' ); - expect(CoreManager.setSchemaController.bind(null, { - send: function() {}, - get: function() {}, - create: function() {}, - update: function() {}, - delete: function() {}, - purge: function() {}, - })).not.toThrow(); + expect( + CoreManager.setSchemaController.bind(null, { + send: function () {}, + get: function () {}, + create: function () {}, + update: function () {}, + delete: function () {}, + purge: function () {}, + }) + ).not.toThrow(); }); it('can set and get SchemaController', () => { const controller = { - send: function() {}, - get: function() {}, - create: function() {}, - update: function() {}, - delete: function() {}, - purge: function() {}, + send: function () {}, + get: function () {}, + create: function () {}, + update: function () {}, + delete: function () {}, + purge: function () {}, }; CoreManager.setSchemaController(controller); @@ -363,22 +405,24 @@ describe('CoreManager', () => { 'LocalDatastoreController must implement pinWithName()' ); - expect(CoreManager.setLocalDatastoreController.bind(null, { - fromPinWithName: function() {}, - pinWithName: function() {}, - unPinWithName: function() {}, - getAllContents: function() {}, - clear: function() {} - })).not.toThrow(); + expect( + CoreManager.setLocalDatastoreController.bind(null, { + fromPinWithName: function () {}, + pinWithName: function () {}, + unPinWithName: function () {}, + getAllContents: function () {}, + clear: function () {}, + }) + ).not.toThrow(); }); it('can set and get setLocalDatastoreController', () => { const controller = { - fromPinWithName: function() {}, - pinWithName: function() {}, - unPinWithName: function() {}, - getAllContents: function() {}, - clear: function() {} + fromPinWithName: function () {}, + pinWithName: function () {}, + unPinWithName: function () {}, + getAllContents: function () {}, + clear: function () {}, }; CoreManager.setLocalDatastoreController(controller); @@ -387,12 +431,12 @@ describe('CoreManager', () => { it('can set and get WebSocketController', () => { const controller = { - onopen: function() {}, - onmessage: function() {}, - onclose: function() {}, - onerror: function() {}, - send: function() {}, - close: function() {}, + onopen: function () {}, + onmessage: function () {}, + onclose: function () {}, + onerror: function () {}, + send: function () {}, + close: function () {}, }; CoreManager.setWebSocketController(controller); diff --git a/src/__tests__/FacebookUtils-test.js b/src/__tests__/FacebookUtils-test.js index 4dfec402f..b846bfec7 100644 --- a/src/__tests__/FacebookUtils-test.js +++ b/src/__tests__/FacebookUtils-test.js @@ -10,7 +10,7 @@ jest.dontMock('../FacebookUtils'); class MockUser { - constructor () { + constructor() { this.className = '_User'; this.attributes = {}; } @@ -35,7 +35,7 @@ describe('FacebookUtils', () => { }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, getAuthResponse: () => authResponse, @@ -82,12 +82,11 @@ describe('FacebookUtils', () => { }); it('can init with options', () => { - jest.spyOn(console, 'warn') - .mockImplementationOnce(() => { - return { - call: () => {} - } - }) + jest.spyOn(console, 'warn').mockImplementationOnce(() => { + return { + call: () => {}, + }; + }); FacebookUtils.init({ status: true }); expect(console.warn).toHaveBeenCalled(); }); @@ -108,7 +107,7 @@ describe('FacebookUtils', () => { FacebookUtils.init(); const user = new MockUser(); const authData = { - id: '1234' + id: '1234', }; jest.spyOn(user, 'linkWith'); await FacebookUtils.link(user, authData); @@ -120,7 +119,11 @@ describe('FacebookUtils', () => { const user = new MockUser(); jest.spyOn(user, 'linkWith'); await FacebookUtils.link(user, {}, { useMasterKey: true }); - expect(user.linkWith).toHaveBeenCalledWith('facebook', { authData: {} }, { useMasterKey: true }); + expect(user.linkWith).toHaveBeenCalledWith( + 'facebook', + { authData: {} }, + { useMasterKey: true } + ); }); it('can check isLinked', async () => { @@ -163,7 +166,11 @@ describe('FacebookUtils', () => { FacebookUtils.init(); jest.spyOn(MockUser, 'logInWith'); await FacebookUtils.logIn({}, { useMasterKey: true }); - expect(MockUser.logInWith).toHaveBeenCalledWith('facebook', { authData: {} }, {useMasterKey: true }); + expect(MockUser.logInWith).toHaveBeenCalledWith( + 'facebook', + { authData: {} }, + { useMasterKey: true } + ); }); it('provider getAuthType', async () => { @@ -200,7 +207,7 @@ describe('FacebookUtils provider', () => { }; jest.spyOn(global.FB, 'logout'); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: '1234'}); + provider.restoreAuthentication({ id: '1234' }); expect(global.FB.logout).toHaveBeenCalled(); }); @@ -214,7 +221,7 @@ describe('FacebookUtils provider', () => { FacebookUtils.init({ status: false }); jest.spyOn(global.FB, 'init'); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: '1234'}); + provider.restoreAuthentication({ id: '1234' }); expect(global.FB.init).toHaveBeenCalled(); }); @@ -228,14 +235,14 @@ describe('FacebookUtils provider', () => { FacebookUtils.init({ status: false }); jest.spyOn(global.FB, 'init'); const provider = FacebookUtils._getAuthProvider(); - provider.restoreAuthentication({ id: '1234'}); + provider.restoreAuthentication({ id: '1234' }); expect(global.FB.init).toHaveBeenCalled(); }); it('authenticate without FB error', async () => { global.FB = undefined; const options = { - error: () => {} + error: () => {}, }; jest.spyOn(options, 'error'); const provider = FacebookUtils._getAuthProvider(); @@ -254,28 +261,32 @@ describe('FacebookUtils provider', () => { }; global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({ authResponse }); }, }; const options = { - success: () => {} + success: () => {}, }; jest.spyOn(options, 'success'); const provider = FacebookUtils._getAuthProvider(); provider.authenticate(options); - expect(options.success).toHaveBeenCalledWith(provider, { access_token: 'access_token', expiration_date: null, id: '1234' }); + expect(options.success).toHaveBeenCalledWith(provider, { + access_token: 'access_token', + expiration_date: null, + id: '1234', + }); }); it('authenticate with no FB response', async () => { global.FB = { init: () => {}, - login: (cb) => { + login: cb => { cb({}); }, }; const options = { - error: () => {} + error: () => {}, }; jest.spyOn(options, 'error'); const provider = FacebookUtils._getAuthProvider(); diff --git a/src/__tests__/Hooks-test.js b/src/__tests__/Hooks-test.js index a67f3dbd5..dcf3af16e 100644 --- a/src/__tests__/Hooks-test.js +++ b/src/__tests__/Hooks-test.js @@ -1,11 +1,11 @@ /** -* Copyright (c) 2015-present, Parse, LLC. -* All rights reserved. -* -* This source code is licensed under the BSD-style license found in the -* LICENSE file in the root directory of this source tree. An additional grant -* of patent rights can be found in the PATENTS file in the same directory. -*/ + * Copyright (c) 2015-present, Parse, LLC. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ jest.dontMock('../ParseHooks'); jest.dontMock('../CoreManager'); @@ -22,9 +22,11 @@ const { sendRequest } = defaultController; describe('Hooks', () => { beforeEach(() => { const run = jest.fn(); - run.mockReturnValue(Promise.resolve({ - result: {} - })); + run.mockReturnValue( + Promise.resolve({ + result: {}, + }) + ); defaultController.sendRequest = run; CoreManager.setHooksController(defaultController); }); @@ -32,179 +34,226 @@ describe('Hooks', () => { it('shoud properly build GET functions', () => { Hooks.getFunctions(); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['GET', '/hooks/functions']); + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'GET', + '/hooks/functions', + ]); }); it('shoud properly build GET triggers', () => { Hooks.getTriggers(); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['GET', '/hooks/triggers']); - }) + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'GET', + '/hooks/triggers', + ]); + }); it('shoud properly build GET function', () => { Hooks.getFunction('functionName'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['GET', '/hooks/functions/functionName']); - }) + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'GET', + '/hooks/functions/functionName', + ]); + }); it('shoud properly build GET trigger', () => { Hooks.getTrigger('MyClass', 'beforeSave'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['GET', '/hooks/triggers/MyClass/beforeSave']); - }) + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'GET', + '/hooks/triggers/MyClass/beforeSave', + ]); + }); it('shoud properly build POST function', () => { Hooks.createFunction('myFunction', 'https://dummy.com'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['POST', '/hooks/functions', { + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'POST', + '/hooks/functions', + { functionName: 'myFunction', - url: 'https://dummy.com' - }]); - }) + url: 'https://dummy.com', + }, + ]); + }); it('shoud properly build POST trigger', () => { Hooks.createTrigger('MyClass', 'beforeSave', 'https://dummy.com'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['POST', '/hooks/triggers', { + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'POST', + '/hooks/triggers', + { className: 'MyClass', triggerName: 'beforeSave', - url: 'https://dummy.com' - }]); - }) + url: 'https://dummy.com', + }, + ]); + }); it('shoud properly build PUT function', () => { Hooks.updateFunction('myFunction', 'https://dummy.com'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['PUT', '/hooks/functions/myFunction', { - url: 'https://dummy.com' - }]); - }) + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'PUT', + '/hooks/functions/myFunction', + { + url: 'https://dummy.com', + }, + ]); + }); it('shoud properly build PUT trigger', () => { Hooks.updateTrigger('MyClass', 'beforeSave', 'https://dummy.com'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['PUT', '/hooks/triggers/MyClass/beforeSave', { - url: 'https://dummy.com' - }]); - }) - + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'PUT', + '/hooks/triggers/MyClass/beforeSave', + { + url: 'https://dummy.com', + }, + ]); + }); it('shoud properly build removeFunction', () => { Hooks.removeFunction('myFunction'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['PUT', '/hooks/functions/myFunction', { "__op": "Delete" }]); - }) + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'PUT', + '/hooks/functions/myFunction', + { __op: 'Delete' }, + ]); + }); it('shoud properly build removeTrigger', () => { Hooks.removeTrigger('MyClass', 'beforeSave'); - expect(CoreManager.getHooksController().sendRequest.mock.calls[0]) - .toEqual(['PUT', '/hooks/triggers/MyClass/beforeSave', { "__op": "Delete" }]); - }) - - it('shoud throw invalid create', async (done) => { - const p1 = Hooks.create({functionName: 'myFunction'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p2 = Hooks.create({url: 'http://dummy.com'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p3 = Hooks.create({className: 'MyClass'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p4 = Hooks.create({className: 'MyClass', url: 'http://dummy.com'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p5 = Hooks.create({className: 'MyClass', triggerName: 'beforeSave'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); + expect(CoreManager.getHooksController().sendRequest.mock.calls[0]).toEqual([ + 'PUT', + '/hooks/triggers/MyClass/beforeSave', + { __op: 'Delete' }, + ]); + }); + + it('shoud throw invalid create', async done => { + const p1 = Hooks.create({ functionName: 'myFunction' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p2 = Hooks.create({ url: 'http://dummy.com' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p3 = Hooks.create({ className: 'MyClass' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p4 = Hooks.create({ className: 'MyClass', url: 'http://dummy.com' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p5 = Hooks.create({ className: 'MyClass', triggerName: 'beforeSave' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); await Promise.all([p1, p2, p3, p4, p5]); done(); - }) - - it('shoud throw invalid update', async (done) => { - const p1 = Hooks.update({functionssName: 'myFunction'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p2 = Hooks.update({className: 'MyClass'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p3 = Hooks.update({className: 'MyClass', url: 'http://dummy.com'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - await Promise.all([p1,p2,p3]); + }); + + it('shoud throw invalid update', async done => { + const p1 = Hooks.update({ functionssName: 'myFunction' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p2 = Hooks.update({ className: 'MyClass' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p3 = Hooks.update({ className: 'MyClass', url: 'http://dummy.com' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + await Promise.all([p1, p2, p3]); done(); - }) - - it('shoud throw invalid remove', async (done) => { - const p1 = Hooks.remove({functionssName: 'myFunction'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p2 = Hooks.remove({className: 'MyClass'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); - - const p3 = Hooks.remove({className: 'MyClass', url: 'http://dummy.com'}).then(() => { - done.fail('should not succeed') - }).catch((err) => { - expect(err.code).toBe(143); - expect(err.error).toBe('invalid hook declaration'); - }); + }); + + it('shoud throw invalid remove', async done => { + const p1 = Hooks.remove({ functionssName: 'myFunction' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p2 = Hooks.remove({ className: 'MyClass' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); + + const p3 = Hooks.remove({ className: 'MyClass', url: 'http://dummy.com' }) + .then(() => { + done.fail('should not succeed'); + }) + .catch(err => { + expect(err.code).toBe(143); + expect(err.error).toBe('invalid hook declaration'); + }); await Promise.all([p1, p2, p3]); done(); - }) + }); it('should sendRequest', async () => { defaultController.sendRequest = sendRequest; - const request = function() { + const request = function () { return Promise.resolve(12); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); @@ -214,7 +263,7 @@ describe('Hooks', () => { it('handle sendRequest error', async () => { defaultController.sendRequest = sendRequest; - const request = function() { + const request = function () { return Promise.resolve(undefined); }; CoreManager.setRESTController({ request, ajax: jest.fn() }); diff --git a/src/__tests__/InstallationController-test.js b/src/__tests__/InstallationController-test.js index 9a672208b..7d22f2466 100644 --- a/src/__tests__/InstallationController-test.js +++ b/src/__tests__/InstallationController-test.js @@ -28,42 +28,46 @@ describe('InstallationController', () => { InstallationController._clearCache(); }); - it('generates a new installation id when there is none', (done) => { - InstallationController.currentInstallationId().then((iid) => { + it('generates a new installation id when there is none', done => { + InstallationController.currentInstallationId().then(iid => { expect(typeof iid).toBe('string'); expect(iid.length).toBeGreaterThan(0); done(); }); }); - it('caches the installation id', (done) => { + it('caches the installation id', done => { let iid = null; - InstallationController.currentInstallationId().then((i) => { - iid = i; - Storage._clear(); - return InstallationController.currentInstallationId(); - }).then((i) => { - expect(i).toBe(iid); - done(); - }); + InstallationController.currentInstallationId() + .then(i => { + iid = i; + Storage._clear(); + return InstallationController.currentInstallationId(); + }) + .then(i => { + expect(i).toBe(iid); + done(); + }); }); - it('permanently stores the installation id', (done) => { + it('permanently stores the installation id', done => { let iid = null; - InstallationController.currentInstallationId().then((i) => { - iid = i; - InstallationController._clearCache(); - return InstallationController.currentInstallationId(); - }).then((i) => { - expect(i).toBe(iid); - done(); - }); + InstallationController.currentInstallationId() + .then(i => { + iid = i; + InstallationController._clearCache(); + return InstallationController.currentInstallationId(); + }) + .then(i => { + expect(i).toBe(iid); + done(); + }); }); - it('can set installation id', (done) => { + it('can set installation id', done => { const iid = '12345678'; InstallationController._setInstallationIdCache(iid); - InstallationController.currentInstallationId().then((i) => { + InstallationController.currentInstallationId().then(i => { expect(i).toBe(iid); done(); }); diff --git a/src/__tests__/LiveQueryClient-test.js b/src/__tests__/LiveQueryClient-test.js index ae52d92bd..812ebb978 100644 --- a/src/__tests__/LiveQueryClient-test.js +++ b/src/__tests__/LiveQueryClient-test.js @@ -63,7 +63,7 @@ describe('LiveQueryClient', () => { }).toThrow('You need to set a proper Parse LiveQuery server url before using LiveQueryClient'); }); - it('WebSocketController required', (done) => { + it('WebSocketController required', done => { const WebSocketImplementation = CoreManager.getWebSocketController(); CoreManager.setWebSocketController(); const liveQueryClient = new LiveQueryClient({ @@ -71,13 +71,13 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); - liveQueryClient.on('error', (error) => { + liveQueryClient.on('error', error => { expect(error).toBe('Can not find WebSocket implementation'); CoreManager.setWebSocketController(WebSocketImplementation); done(); - }) + }); liveQueryClient.open(); }); @@ -87,14 +87,14 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const subscription = { - id: 1 - } + id: 1, + }; liveQueryClient.subscriptions.set(1, subscription); liveQueryClient.unsubscribe(subscription); @@ -105,7 +105,7 @@ describe('LiveQueryClient', () => { const message = JSON.parse(messageStr); expect(message).toEqual({ op: 'unsubscribe', - requestId: 1 + requestId: 1, }); }); @@ -115,7 +115,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); expect(liveQueryClient.shouldOpen()).toBe(true); liveQueryClient.close(); @@ -140,12 +140,12 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Mock _getWebSocketImplementation - liveQueryClient._getWebSocketImplementation = function() { + liveQueryClient._getWebSocketImplementation = function () { return jest.fn(); - } + }; // Mock handlers liveQueryClient._handleWebSocketOpen = jest.fn(); liveQueryClient._handleWebSocketMessage = jest.fn(); @@ -173,10 +173,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; liveQueryClient._handleWebSocketOpen(); @@ -197,18 +197,18 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const data = { op: 'connected', - clientId: 1 + clientId: 1, }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - liveQueryClient.on('open', function() { + liveQueryClient.on('open', function () { isChecked = true; }); @@ -226,18 +226,18 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const data = { op: 'connected', - clientId: 1 + clientId: 1, }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - liveQueryClient.on('open', function() { + liveQueryClient.on('open', function () { isChecked = true; }); jest.spyOn(liveQueryClient, 'resubscribe'); @@ -257,7 +257,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -267,14 +267,14 @@ describe('LiveQueryClient', () => { const data = { op: 'subscribed', clientId: 1, - requestId: 1 + requestId: 1, }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - subscription.on('open', function() { + subscription.on('open', function () { isChecked = true; }); @@ -289,7 +289,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); @@ -298,11 +298,11 @@ describe('LiveQueryClient', () => { const data = { op: 'unsubscribed', clientId: 1, - requestId: 1 + requestId: 1, }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; liveQueryClient._handleWebSocketMessage(event); expect(liveQueryClient.subscriptions.size).toBe(1); }); @@ -313,19 +313,19 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const data = { op: 'error', clientId: 1, - error: 'error' + error: 'error', }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - liveQueryClient.on('error', function(error) { + liveQueryClient.on('error', function (error) { isChecked = true; expect(error).toEqual('error'); }); @@ -341,7 +341,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); subscription.subscribePromise = resolvingPromise(); @@ -351,14 +351,14 @@ describe('LiveQueryClient', () => { op: 'error', clientId: 1, requestId: 1, - error: 'error thrown' + error: 'error thrown', }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - subscription.on('error', function(error) { + subscription.on('error', function (error) { isChecked = true; expect(error).toEqual('error thrown'); }); @@ -375,7 +375,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -386,14 +386,14 @@ describe('LiveQueryClient', () => { op: 'create', clientId: 1, requestId: 1, - object: object._toFullJSON() + object: object._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - subscription.on('create', function(parseObject) { + subscription.on('create', function (parseObject) { isChecked = true; expect(parseObject.get('key')).toEqual('value'); expect(parseObject.get('className')).toBeUndefined(); @@ -411,7 +411,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const object = new ParseObject('Test'); object.set('key', 'value'); @@ -419,11 +419,11 @@ describe('LiveQueryClient', () => { op: 'create', clientId: 1, requestId: 1, - object: object._toFullJSON() + object: object._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; liveQueryClient._handleWebSocketMessage(event); }); @@ -433,7 +433,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -450,8 +450,8 @@ describe('LiveQueryClient', () => { original: original._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; subscription.on('update', (parseObject, parseOriginalObject) => { @@ -476,7 +476,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -493,23 +493,18 @@ describe('LiveQueryClient', () => { original: original._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; - jest.spyOn( - mockLocalDatastore, - '_updateObjectIfPinned' - ) + jest + .spyOn(mockLocalDatastore, '_updateObjectIfPinned') .mockImplementationOnce(() => Promise.resolve()); - const spy = jest.spyOn( - ParseObject, - 'fromJSON' - ) + const spy = jest + .spyOn(ParseObject, 'fromJSON') .mockImplementationOnce(() => original) .mockImplementationOnce(() => object); - mockLocalDatastore.isEnabled = true; let isChecked = false; @@ -533,7 +528,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -552,8 +547,8 @@ describe('LiveQueryClient', () => { original: original._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; let isChecked = false; subscription.on('update', (parseObject, parseOriginalObject) => { isChecked = true; @@ -572,18 +567,18 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); // Register checked in advance let isChecked = false; - subscription.on('close', function() { + subscription.on('close', function () { isChecked = true; }); let isCheckedAgain = false; - liveQueryClient.on('close', function() { + liveQueryClient.on('close', function () { isCheckedAgain = true; }); @@ -599,18 +594,18 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); // Register checked in advance let isChecked = false; - subscription.on('close', function() { + subscription.on('close', function () { isChecked = true; }); let isCheckedAgain = false; - liveQueryClient.on('close', function() { + liveQueryClient.on('close', function () { isCheckedAgain = true; }); liveQueryClient.open(); @@ -627,7 +622,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.open = jest.fn(); @@ -648,7 +643,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.open = jest.fn(); @@ -675,11 +670,11 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const error = {}; let isChecked = false; - liveQueryClient.on('error', function(errorAgain) { + liveQueryClient.on('error', function (errorAgain) { isChecked = true; expect(errorAgain).toEqual(error); }); @@ -689,18 +684,18 @@ describe('LiveQueryClient', () => { expect(isChecked).toBe(true); }); - it('can handle WebSocket error message with subscriptions', (done) => { + it('can handle WebSocket error message with subscriptions', done => { const liveQueryClient = new LiveQueryClient({ applicationId: 'applicationId', serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); - const error = {} - subscription.on('error', (errorAgain) => { + const error = {}; + subscription.on('error', errorAgain => { expect(errorAgain).toEqual(error); done(); }); @@ -714,7 +709,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); expect(liveQueryClient.additionalProperties).toBe(true); const data = { @@ -724,10 +719,10 @@ describe('LiveQueryClient', () => { error: 'Additional properties not allowed', }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; let isChecked = false; - liveQueryClient.on('error', function(error) { + liveQueryClient.on('error', function (error) { isChecked = true; expect(error).toEqual(data.error); }); @@ -746,10 +741,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); @@ -771,9 +766,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value' - } - } + key: 'value', + }, + }, }); }); @@ -783,10 +778,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); @@ -810,9 +805,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value' - } - } + key: 'value', + }, + }, }); }); @@ -822,14 +817,14 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const subscription = { - id: 1 - } + id: 1, + }; liveQueryClient.subscriptions.set(1, subscription); liveQueryClient.unsubscribe(subscription); @@ -840,7 +835,7 @@ describe('LiveQueryClient', () => { const message = JSON.parse(messageStr); expect(message).toEqual({ op: 'unsubscribe', - requestId: 1 + requestId: 1, }); }); @@ -850,10 +845,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; liveQueryClient.unsubscribe(); liveQueryClient.connectPromise.resolve(); @@ -867,10 +862,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); @@ -889,9 +884,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value' - } - } + key: 'value', + }, + }, }); }); @@ -901,10 +896,10 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.socket = { - send: jest.fn() + send: jest.fn(), }; const query = new ParseQuery('Test'); query.equalTo('key', 'value'); @@ -924,9 +919,9 @@ describe('LiveQueryClient', () => { query: { className: 'Test', where: { - key: 'value' - } - } + key: 'value', + }, + }, }); }); @@ -936,21 +931,21 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); liveQueryClient.state = 'connected'; liveQueryClient.socket = { - close: jest.fn() - } + close: jest.fn(), + }; const subscription = new events.EventEmitter(); liveQueryClient.subscriptions.set(1, subscription); // Register checked in advance let isChecked = false; - subscription.on('close', function() { + subscription.on('close', function () { isChecked = true; }); let isCheckedAgain = false; - liveQueryClient.on('close', function() { + liveQueryClient.on('close', function () { isCheckedAgain = true; }); @@ -972,7 +967,7 @@ describe('LiveQueryClient', () => { serverURL: 'ws://test', javascriptKey: 'javascriptKey', masterKey: 'masterKey', - sessionToken: 'sessionToken' + sessionToken: 'sessionToken', }); // Add mock subscription const subscription = new events.EventEmitter(); @@ -986,11 +981,11 @@ describe('LiveQueryClient', () => { object: object._toFullJSON(), }; const event = { - data: JSON.stringify(data) - } + data: JSON.stringify(data), + }; // Register checked in advance let isChecked = false; - subscription.on('create', function(parseObject) { + subscription.on('create', function (parseObject) { isChecked = true; expect(parseObject instanceof MyExtendedClass).toBe(true); expect(parseObject.get('key')).toEqual('value'); diff --git a/src/__tests__/LocalDatastore-test.js b/src/__tests__/LocalDatastore-test.js index b0038459f..7dce00212 100644 --- a/src/__tests__/LocalDatastore-test.js +++ b/src/__tests__/LocalDatastore-test.js @@ -16,7 +16,7 @@ const encode = require('../encode').default; let objectCount = 0; class MockObject { - constructor (className) { + constructor(className) { this.className = className; this.attributes = {}; @@ -40,7 +40,7 @@ class MockObject { _toFullJSON() { const json = { __type: 'Object', - className: this.className + className: this.className, }; for (const attr in this.attributes) { if (this.attributes[attr].id) { @@ -117,7 +117,12 @@ const KEY1 = LocalDatastore.getKeyForObject(item1); const KEY2 = LocalDatastore.getKeyForObject(item2); const KEY3 = LocalDatastore.getKeyForObject(item2); -import { DEFAULT_PIN, PIN_PREFIX, OBJECT_PREFIX, isLocalDatastoreKey } from '../LocalDatastoreUtils'; +import { + DEFAULT_PIN, + PIN_PREFIX, + OBJECT_PREFIX, + isLocalDatastoreKey, +} from '../LocalDatastoreUtils'; describe('LocalDatastore', () => { beforeEach(() => { @@ -165,9 +170,11 @@ describe('LocalDatastore', () => { object._localId = 'local0'; object.id = null; await LocalDatastore._handlePinAllWithName('test_pin', [object]); - expect(mockLocalStorageController.pinWithName.mock.calls[0][0]).toEqual('Parse_LDS_Item_local0'); + expect(mockLocalStorageController.pinWithName.mock.calls[0][0]).toEqual( + 'Parse_LDS_Item_local0' + ); expect(mockLocalStorageController.pinWithName.mock.calls[0][1]).toEqual([ - { __type: 'Object', className: 'Item', _localId: 'local0' } + { __type: 'Object', className: 'Item', _localId: 'local0' }, ]); }); @@ -199,9 +206,7 @@ describe('LocalDatastore', () => { const LDS = { [DEFAULT_PIN]: [KEY1, KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName(DEFAULT_PIN, [item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(DEFAULT_PIN, [KEY2]); @@ -211,12 +216,12 @@ describe('LocalDatastore', () => { const LDS = { parsePin_test_pin: [KEY1, KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName('test_pin', [item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin', [KEY2]); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin', [ + KEY2, + ]); }); it('_handleUnPinAllWithName default pin remove pinName', async () => { @@ -224,9 +229,7 @@ describe('LocalDatastore', () => { const LDS = { [DEFAULT_PIN]: [], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName(DEFAULT_PIN, [object]); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(2); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(DEFAULT_PIN); @@ -237,9 +240,7 @@ describe('LocalDatastore', () => { const LDS = { [PIN_PREFIX + 'test_pin']: [], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName('test_pin', [object]); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(2); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin'); @@ -252,15 +253,16 @@ describe('LocalDatastore', () => { [PIN_PREFIX + 'test_pin_2']: objects, [KEY1]: [item1._toFullJSON()], [KEY2]: [item2._toFullJSON()], - } - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + }; + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._handleUnPinAllWithName('test_pin', [item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin', [KEY2, KEY3]); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(PIN_PREFIX + 'test_pin', [ + KEY2, + KEY3, + ]); }); it('_updateObjectIfPinned not pinned', async () => { @@ -271,9 +273,7 @@ describe('LocalDatastore', () => { }); it('_updateObjectIfPinned if pinned', async () => { - mockLocalStorageController - .fromPinWithName - .mockImplementationOnce(() => [item1]); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => [item1]); LocalDatastore.isEnabled = true; await LocalDatastore._updateObjectIfPinned(item1); @@ -282,7 +282,9 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual([item1]); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(KEY1, [item1._toFullJSON()]); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(KEY1, [ + item1._toFullJSON(), + ]); }); it('_updateLocalIdForObject not pinned', async () => { @@ -299,13 +301,9 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [localKey], [localKey]: [json], }; - mockLocalStorageController - .fromPinWithName - .mockImplementationOnce(() => json); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._updateLocalIdForObject(localId, object); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); @@ -320,13 +318,9 @@ describe('LocalDatastore', () => { [PIN_PREFIX + 'test_pin']: [localKey], [localKey]: [json], }; - mockLocalStorageController - .fromPinWithName - .mockImplementationOnce(() => json); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._updateLocalIdForObject(localId, object); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(2); @@ -340,13 +334,9 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [object.id], [object.id]: [json], }; - mockLocalStorageController - .fromPinWithName - .mockImplementationOnce(() => json); + mockLocalStorageController.fromPinWithName.mockImplementationOnce(() => json); - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._updateLocalIdForObject(localId, object); @@ -354,10 +344,15 @@ describe('LocalDatastore', () => { expect(mockLocalStorageController.fromPinWithName.mock.results[0].value).toEqual(json); expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith(`${OBJECT_PREFIX}Item_${localId}`); + expect(mockLocalStorageController.unPinWithName).toHaveBeenCalledWith( + `${OBJECT_PREFIX}Item_${localId}` + ); expect(mockLocalStorageController.pinWithName).toHaveBeenCalledTimes(1); - expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith(`${OBJECT_PREFIX}Item_${object.id}`, json); + expect(mockLocalStorageController.pinWithName).toHaveBeenCalledWith( + `${OBJECT_PREFIX}Item_${object.id}`, + json + ); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); }); @@ -369,9 +364,7 @@ describe('LocalDatastore', () => { [KEY1]: [json], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const results = await LocalDatastore._serializeObjectsFromPinName(null); expect(results).toEqual([json]); @@ -388,9 +381,7 @@ describe('LocalDatastore', () => { randomName: [object.id], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); expect(results).toEqual([]); @@ -410,15 +401,12 @@ describe('LocalDatastore', () => { [PIN_PREFIX + 'testPin']: [obj1.id, obj2.id, obj3.id], }; - mockLocalStorageController - .fromPinWithName + mockLocalStorageController.fromPinWithName .mockImplementationOnce(() => LDS[obj1.id]) .mockImplementationOnce(() => LDS[obj2.id]) .mockImplementationOnce(() => LDS[obj3.id]); - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const results = await LocalDatastore._serializeObjectsFromPinName('testPin'); expect(results).toEqual([obj1._toFullJSON(), obj2._toFullJSON(), obj3._toFullJSON()]); @@ -432,9 +420,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: null, }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const results = await LocalDatastore._serializeObjectsFromPinName(DEFAULT_PIN); expect(results).toEqual([]); @@ -452,9 +438,7 @@ describe('LocalDatastore', () => { [objectKey]: [json], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const result = await LocalDatastore._serializeObject(objectKey); expect(result).toEqual(json); @@ -491,9 +475,7 @@ describe('LocalDatastore', () => { [childKey]: [childJSON], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); const expectedResults = parent._toFullJSON(); expectedResults.child = childJSON; @@ -504,9 +486,7 @@ describe('LocalDatastore', () => { it('_destroyObjectIfPinned no objects found in pinName', async () => { let LDS = {}; LocalDatastore.isEnabled = true; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); await LocalDatastore._destroyObjectIfPinned(item1); expect(mockLocalStorageController.getAllContents).toHaveBeenCalledTimes(1); @@ -520,9 +500,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item1); @@ -541,9 +519,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item2); @@ -561,9 +537,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1, KEY2], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); LocalDatastore.isEnabled = true; await LocalDatastore._destroyObjectIfPinned(item1); @@ -625,9 +599,7 @@ describe('LocalDatastore', () => { LocalDatastore.isSyncing = false; const LDS = {}; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); jest.spyOn(mockLocalStorageController, 'pinWithName'); await LocalDatastore.updateFromServer(); @@ -644,9 +616,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); item1.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); @@ -677,9 +647,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [USER_KEY], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); user.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([user])); @@ -711,9 +679,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1, OBJECT_KEY], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); item1.set('updatedField', 'foo'); mockQueryFind.mockImplementationOnce(() => Promise.resolve([item1])); @@ -738,9 +704,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); mockQueryFind.mockImplementationOnce(() => { expect(LocalDatastore.isSyncing).toBe(true); @@ -773,9 +737,7 @@ describe('LocalDatastore', () => { [DEFAULT_PIN]: [KEY1], }; - mockLocalStorageController - .getAllContents - .mockImplementationOnce(() => LDS); + mockLocalStorageController.getAllContents.mockImplementationOnce(() => LDS); mockQueryFind .mockImplementationOnce(() => Promise.resolve([item1, item2])) @@ -815,8 +777,12 @@ describe('LocalDatastore (BrowserStorageController)', () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); - expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()] }); - expect(await LocalDatastore._getRawStorage()).toEqual({ [KEY1]: JSON.stringify([item1._toFullJSON()]) }); + expect(await LocalDatastore._getAllContents()).toEqual({ + [KEY1]: [item1._toFullJSON()], + }); + expect(await LocalDatastore._getRawStorage()).toEqual({ + [KEY1]: JSON.stringify([item1._toFullJSON()]), + }); }); it('can remove values', async () => { @@ -830,7 +796,8 @@ describe('LocalDatastore (BrowserStorageController)', () => { it('can handle getAllContent error', async () => { await LocalDatastore.pinWithName('_default', [{ value: 'WILL_BE_MOCKED' }]); - const windowSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'getItem') + const windowSpy = jest + .spyOn(Object.getPrototypeOf(window.localStorage), 'getItem') .mockImplementationOnce(() => { return '[1, ]'; }); @@ -843,7 +810,8 @@ describe('LocalDatastore (BrowserStorageController)', () => { }); it('can handle store error', async () => { - const windowSpy = jest.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem') + const windowSpy = jest + .spyOn(Object.getPrototypeOf(window.localStorage), 'setItem') .mockImplementationOnce(() => { throw new Error('error thrown'); }); @@ -866,8 +834,12 @@ describe('LocalDatastore (DefaultStorageController)', () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); - expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()] }); - expect(await LocalDatastore._getRawStorage()).toEqual({ [KEY1]: JSON.stringify([item1._toFullJSON()]) }); + expect(await LocalDatastore._getAllContents()).toEqual({ + [KEY1]: [item1._toFullJSON()], + }); + expect(await LocalDatastore._getRawStorage()).toEqual({ + [KEY1]: JSON.stringify([item1._toFullJSON()]), + }); }); it('can remove values', async () => { @@ -891,8 +863,12 @@ describe('LocalDatastore (RNDatastoreController)', () => { expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([]); await LocalDatastore.pinWithName(KEY1, [item1._toFullJSON()]); expect(await LocalDatastore.fromPinWithName(KEY1)).toEqual([item1._toFullJSON()]); - expect(await LocalDatastore._getAllContents()).toEqual({ [KEY1]: [item1._toFullJSON()] }); - expect(await LocalDatastore._getRawStorage()).toEqual({ [KEY1]: JSON.stringify([item1._toFullJSON()]) }); + expect(await LocalDatastore._getAllContents()).toEqual({ + [KEY1]: [item1._toFullJSON()], + }); + expect(await LocalDatastore._getRawStorage()).toEqual({ + [KEY1]: JSON.stringify([item1._toFullJSON()]), + }); }); it('can remove values', async () => { @@ -940,7 +916,7 @@ describe('LocalDatastore (RNDatastoreController)', () => { }, getAllKeys(cb) { cb(undefined, [KEY1, 'DO_NOT_CLEAR']); - } + }, }; jest.spyOn(console, 'error').mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); @@ -954,7 +930,7 @@ describe('LocalDatastore (RNDatastoreController)', () => { }, getAllKeys(cb) { cb(undefined, [KEY1, 'DO_NOT_CLEAR']); - } + }, }; jest.spyOn(console, 'error').mockImplementationOnce(() => {}); CoreManager.setAsyncStorage(mockStorageError); diff --git a/src/__tests__/ObjectStateMutations-test.js b/src/__tests__/ObjectStateMutations-test.js index 5162de908..08c750719 100644 --- a/src/__tests__/ObjectStateMutations-test.js +++ b/src/__tests__/ObjectStateMutations-test.js @@ -16,10 +16,10 @@ jest.dontMock('../ParseOp'); jest.dontMock('../ParseRelation'); jest.dontMock('../TaskQueue'); -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; }; -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; jest.setMock('../ParseObject', mockObject); const ObjectStateMutations = require('../ObjectStateMutations'); @@ -74,9 +74,11 @@ describe('ObjectStateMutations', () => { it('can merge the first op set into the next', () => { let pendingOps = [{ counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp('foo') }, {}]; ObjectStateMutations.mergeFirstPendingState(pendingOps); - expect(pendingOps).toEqual([{ counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp('foo') }]); + expect(pendingOps).toEqual([ + { counter: new ParseOps.SetOp(1), name: new ParseOps.SetOp('foo') }, + ]); - pendingOps = [{ counter: new ParseOps.SetOp(1) }, { counter: new ParseOps.IncrementOp(1)}]; + pendingOps = [{ counter: new ParseOps.SetOp(1) }, { counter: new ParseOps.IncrementOp(1) }]; ObjectStateMutations.mergeFirstPendingState(pendingOps); expect(pendingOps).toEqual([{ counter: new ParseOps.SetOp(2) }]); }); @@ -84,15 +86,44 @@ describe('ObjectStateMutations', () => { it('can estimate an attribute value', () => { const serverData = { counter: 12 }; const pendingOps = [{ counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp('foo') }]; - expect(ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'counter')).toBe(14); - expect(ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name')).toBe('foo'); - - pendingOps.push({ counter: new ParseOps.IncrementOp(1), name: new ParseOps.SetOp('override') }); - expect(ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'counter')).toBe(15); - expect(ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name')).toBe('override'); + expect( + ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + 'someClass', + 'someId', + 'counter' + ) + ).toBe(14); + expect( + ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name') + ).toBe('foo'); + + pendingOps.push({ + counter: new ParseOps.IncrementOp(1), + name: new ParseOps.SetOp('override'), + }); + expect( + ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + 'someClass', + 'someId', + 'counter' + ) + ).toBe(15); + expect( + ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'name') + ).toBe('override'); pendingOps.push({ likes: new ParseOps.RelationOp([], []) }); - const relation = ObjectStateMutations.estimateAttribute(serverData, pendingOps, 'someClass', 'someId', 'likes'); + const relation = ObjectStateMutations.estimateAttribute( + serverData, + pendingOps, + 'someClass', + 'someId', + 'likes' + ); expect(relation.parent.id).toBe('someId'); expect(relation.parent.className).toBe('someClass'); expect(relation.key).toBe('likes'); @@ -101,19 +132,31 @@ describe('ObjectStateMutations', () => { it('can estimate all attributes', () => { const serverData = { counter: 12 }; const pendingOps = [{ counter: new ParseOps.IncrementOp(2), name: new ParseOps.SetOp('foo') }]; - expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({ + expect( + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') + ).toEqual({ counter: 14, - name: 'foo' + name: 'foo', }); - pendingOps.push({ counter: new ParseOps.IncrementOp(1), name: new ParseOps.SetOp('override') }); - expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({ + pendingOps.push({ + counter: new ParseOps.IncrementOp(1), + name: new ParseOps.SetOp('override'), + }); + expect( + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') + ).toEqual({ counter: 15, - name: 'override' + name: 'override', }); pendingOps.push({ likes: new ParseOps.RelationOp([], []) }); - const attributes = ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId'); + const attributes = ObjectStateMutations.estimateAttributes( + serverData, + pendingOps, + 'someClass', + 'someId' + ); expect(attributes.likes.parent.id).toBe('someId'); expect(attributes.likes.parent.className).toBe('someClass'); expect(attributes.likes.key).toBe('likes'); @@ -122,17 +165,21 @@ describe('ObjectStateMutations', () => { it('can estimate attributes for nested documents', () => { const serverData = { objectField: { counter: 10, letter: 'a' } }; let pendingOps = [{ 'objectField.counter': new ParseOps.IncrementOp(2) }]; - expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({ + expect( + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') + ).toEqual({ objectField: { counter: 12, - letter: 'a' + letter: 'a', }, }); pendingOps = [{ 'objectField.counter': new ParseOps.SetOp(20) }]; - expect(ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId')).toEqual({ + expect( + ObjectStateMutations.estimateAttributes(serverData, pendingOps, 'someClass', 'someId') + ).toEqual({ objectField: { counter: 20, - letter: 'a' + letter: 'a', }, }); }); @@ -140,7 +187,10 @@ describe('ObjectStateMutations', () => { it('can commit changes from the server', () => { const serverData = {}; const objectCache = {}; - ObjectStateMutations.commitServerChanges(serverData, objectCache, { name: 'foo', data: { count: 5 } }); + ObjectStateMutations.commitServerChanges(serverData, objectCache, { + name: 'foo', + data: { count: 5 }, + }); expect(serverData).toEqual({ name: 'foo', data: { count: 5 } }); expect(objectCache).toEqual({ data: '{"count":5}' }); }); @@ -151,7 +201,7 @@ describe('ObjectStateMutations', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); }); diff --git a/src/__tests__/OfflineQuery-test.js b/src/__tests__/OfflineQuery-test.js index c2e1ca893..5ab209a3d 100644 --- a/src/__tests__/OfflineQuery-test.js +++ b/src/__tests__/OfflineQuery-test.js @@ -19,7 +19,6 @@ const ParsePolygon = require('../ParsePolygon').default; const ParseUser = require('../ParseUser').default; describe('OfflineQuery', () => { - it('matches blank queries', () => { const obj = new ParseObject('Item'); const q = new ParseQuery('Item'); @@ -47,7 +46,7 @@ describe('OfflineQuery', () => { const q = new ParseQuery('Item'); q.equalTo('$foo', 'bar'); try { - matchesQuery(q.className, obj, [], q) + matchesQuery(q.className, obj, [], q); } catch (e) { expect(e.message).toBe('Invalid Key: $foo'); } @@ -56,7 +55,7 @@ describe('OfflineQuery', () => { it('matches queries date field', () => { const date = new Date(); const obj = new ParseObject('Item'); - obj.set('field', date) + obj.set('field', date); const q = new ParseQuery('Item'); q.greaterThanOrEqualTo('field', date); expect(matchesQuery(q.className, obj, [], q)).toBe(true); @@ -64,7 +63,7 @@ describe('OfflineQuery', () => { it('matches queries relation', () => { const obj = new ParseObject('Item'); - const relation = obj.relation("author"); + const relation = obj.relation('author'); const q = relation.query(); expect(matchesQuery(q.className, obj, [], q)).toBe(false); }); @@ -99,11 +98,7 @@ describe('OfflineQuery', () => { longitude: -122.148377, }); const obj = new ParseObject('Person'); - obj - .set('score', 12) - .set('name', 'Bill') - .set('birthday', day) - .set('lastLocation', location); + obj.set('score', 12).set('name', 'Bill').set('birthday', day).set('lastLocation', location); let q = new ParseQuery('Person'); q.equalTo('score', 12); @@ -136,16 +131,22 @@ describe('OfflineQuery', () => { q = new ParseQuery('Person'); q.equalTo('lastLocation', location); expect(matchesQuery(q.className, obj, [], q)).toBe(true); - q.equalTo('lastLocation', new ParseGeoPoint({ - latitude: 37.4848, - longitude: -122.1483, - })); + q.equalTo( + 'lastLocation', + new ParseGeoPoint({ + latitude: 37.4848, + longitude: -122.1483, + }) + ); expect(matchesQuery(q.className, obj, [], q)).toBe(false); - q.equalTo('lastLocation', new ParseGeoPoint({ - latitude: 37.484815, - longitude: -122.148377, - })); + q.equalTo( + 'lastLocation', + new ParseGeoPoint({ + latitude: 37.484815, + longitude: -122.148377, + }) + ); q.equalTo('score', 12); q.equalTo('name', 'Bill'); q.equalTo('birthday', day); @@ -204,10 +205,7 @@ describe('OfflineQuery', () => { it('matches on inequalities', () => { const player = new ParseObject('Person'); - player - .set('score', 12) - .set('name', 'Bill') - .set('birthday', new Date(1980, 2, 4)); + player.set('score', 12).set('name', 'Bill').set('birthday', new Date(1980, 2, 4)); let q = new ParseQuery('Person'); q.lessThan('score', 15); @@ -246,9 +244,7 @@ describe('OfflineQuery', () => { it('matches an $or query', () => { const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + player.set('score', 12).set('name', 'Player 1'); const q = new ParseQuery('Player'); q.equalTo('name', 'Player 1'); @@ -266,16 +262,14 @@ describe('OfflineQuery', () => { it('matches an $and query', () => { const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + player.set('score', 12).set('name', 'Player 1'); const q = new ParseQuery('Player'); q.equalTo('name', 'Player 1'); const q2 = new ParseQuery('Player'); - q2.equalTo('score', 12); + q2.equalTo('score', 12); const q3 = new ParseQuery('Player'); - q3.equalTo('score', 100); + q3.equalTo('score', 100); const andQuery1 = ParseQuery.and(q, q2); const andQuery2 = ParseQuery.and(q, q3); expect(matchesQuery(q.className, player, [], q)).toBe(true); @@ -286,9 +280,7 @@ describe('OfflineQuery', () => { it('matches an $nor query', () => { const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + player.set('score', 12).set('name', 'Player 1'); const q = new ParseQuery('Player'); q.equalTo('name', 'Player 1'); @@ -308,9 +300,7 @@ describe('OfflineQuery', () => { it('matches $regex queries', () => { const player = new ParseObject('Player'); - player - .set('score', 12) - .set('name', 'Player 1'); + player.set('score', 12).set('name', 'Player 1'); let q = new ParseQuery('Player'); q.startsWith('name', 'Play'); @@ -354,7 +344,11 @@ describe('OfflineQuery', () => { expect(matchesQuery(q.className, player, [], q)).toBe(false); q = new ParseQuery('Player'); - q._addCondition('status', '$regex', { test: function() { return true } }); + q._addCondition('status', '$regex', { + test: function () { + return true; + }, + }); expect(matchesQuery(q.className, player, [], q)).toBe(true); }); @@ -403,15 +397,12 @@ describe('OfflineQuery', () => { noLocation.set('name', 'Santa Clara'); const nullLocation = new ParseObject('Checkin'); - nullLocation - .set('name', 'Santa Clara') - .set('location', null); - + nullLocation.set('name', 'Santa Clara').set('location', null); let q = new ParseQuery('Checkin').withinGeoBox( 'location', new ParseGeoPoint(37.708813, -122.526398), - new ParseGeoPoint(37.822802, -122.373962), + new ParseGeoPoint(37.822802, -122.373962) ); expect(matchesQuery(q.className, caltrainStation, [], q)).toBe(true); @@ -422,7 +413,7 @@ describe('OfflineQuery', () => { q = new ParseQuery('Checkin').withinGeoBox( 'location', new ParseGeoPoint(37.822802, -122.373962), - new ParseGeoPoint(37.708813, -122.526398), + new ParseGeoPoint(37.708813, -122.526398) ); expect(matchesQuery(q.className, caltrainStation, [], q)).toBe(false); @@ -431,7 +422,7 @@ describe('OfflineQuery', () => { q = new ParseQuery('Checkin').withinGeoBox( 'location', new ParseGeoPoint(37.708813, -122.373962), - new ParseGeoPoint(37.822802, -122.526398), + new ParseGeoPoint(37.822802, -122.526398) ); expect(matchesQuery(q.className, caltrainStation, [], q)).toBe(false); @@ -440,9 +431,7 @@ describe('OfflineQuery', () => { it('matches on subobjects with dot notation', () => { const message = new ParseObject('Message'); - message - .set('test', 'content') - .set('status', { x: 'read', y: 'delivered' }); + message.set('test', 'content').set('status', { x: 'read', y: 'delivered' }); let q = new ParseQuery('Message'); q.equalTo('status.x', 'read'); @@ -509,13 +498,17 @@ describe('OfflineQuery', () => { message.set('profile', profile); let q = new ParseQuery('Message'); - q.containedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'abc' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'def' })]); + q.containedIn('profile', [ + ParseObject.fromJSON({ className: 'Profile', objectId: 'abc' }), + ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(true); q = new ParseQuery('Message'); - q.containedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'def' })]); + q.containedIn('profile', [ + ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), + ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); @@ -527,16 +520,20 @@ describe('OfflineQuery', () => { message.set('profile', profile); let q = new ParseQuery('Message'); - q.notContainedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' })]); + q.notContainedIn('profile', [ + ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), + ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(true); profile.id = 'def'; message = new ParseObject('Message'); message.set('profile', profile); q = new ParseQuery('Message'); - q.notContainedIn('profile', [ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), - ParseObject.fromJSON({ className: 'Profile', objectId: 'def' })]); + q.notContainedIn('profile', [ + ParseObject.fromJSON({ className: 'Profile', objectId: 'ghi' }), + ParseObject.fromJSON({ className: 'Profile', objectId: 'def' }), + ]); expect(matchesQuery(q.className, message, [], q)).toBe(false); }); @@ -588,8 +585,12 @@ describe('OfflineQuery', () => { let mainQuery = new ParseQuery('Person'); mainQuery.matchesKeyInQuery('hometown', 'location', query); - expect(matchesQuery(mainQuery.className, person1, [person1, person2, restaurant], mainQuery)).toBe(true); - expect(matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery)).toBe(false); + expect( + matchesQuery(mainQuery.className, person1, [person1, person2, restaurant], mainQuery) + ).toBe(true); + expect( + matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery) + ).toBe(false); expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe(false); query = new ParseQuery('Restaurant'); @@ -597,8 +598,17 @@ describe('OfflineQuery', () => { mainQuery = new ParseQuery('Person'); mainQuery.doesNotMatchKeyInQuery('hometown', 'location', query); - expect(matchesQuery(mainQuery.className, person1, [person1, person2, restaurant._toFullJSON()], mainQuery)).toBe(false); - expect(matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery)).toBe(true); + expect( + matchesQuery( + mainQuery.className, + person1, + [person1, person2, restaurant._toFullJSON()], + mainQuery + ) + ).toBe(false); + expect( + matchesQuery(mainQuery.className, person2, [person1, person2, restaurant], mainQuery) + ).toBe(true); expect(matchesQuery(mainQuery.className, person1, [], mainQuery)).toBe(false); }); @@ -619,16 +629,24 @@ describe('OfflineQuery', () => { subQuery.greaterThan('x', 5); let q = new ParseQuery('ParentObject'); q.matchesQuery('child', subQuery); - expect(matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q)).toBe(false); - expect(matchesQuery(q.className, parentObjects[9], [...parentObjects, ...childObjects], q)).toBe(true); + expect( + matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q) + ).toBe(false); + expect( + matchesQuery(q.className, parentObjects[9], [...parentObjects, ...childObjects], q) + ).toBe(true); expect(matchesQuery(q.className, parentObjects[0], [], q)).toBe(false); subQuery = new ParseQuery('ChildObject'); subQuery.greaterThan('x', 5); q = new ParseQuery('ParentObject'); q.doesNotMatchQuery('child', subQuery); - expect(matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q)).toBe(true); - expect(matchesQuery(q.className, parentObjects[9], [...parentObjects, ...childObjects], q)).toBe(false); + expect( + matchesQuery(q.className, parentObjects[0], [...parentObjects, ...childObjects], q) + ).toBe(true); + expect( + matchesQuery(q.className, parentObjects[9], [...parentObjects, ...childObjects], q) + ).toBe(false); expect(matchesQuery(q.className, parentObjects[0], [], q)).toBe(true); }); @@ -649,7 +667,7 @@ describe('OfflineQuery', () => { it('should support withinPolygon query', () => { const sacramento = new ParseObject('Location'); - sacramento.set('location', new ParseGeoPoint(38.52, -121.50)); + sacramento.set('location', new ParseGeoPoint(38.52, -121.5)); sacramento.set('name', 'Sacramento'); const honolulu = new ParseObject('Location'); @@ -658,13 +676,13 @@ describe('OfflineQuery', () => { const sf = new ParseObject('Location'); sf.set('location', new ParseGeoPoint(37.75, -122.68)); - sf.set('name', 'San Francisco') + sf.set('name', 'San Francisco'); const points = [ new ParseGeoPoint(37.85, -122.33), - new ParseGeoPoint(37.85, -122.90), - new ParseGeoPoint(37.68, -122.90), - new ParseGeoPoint(37.68, -122.33) + new ParseGeoPoint(37.85, -122.9), + new ParseGeoPoint(37.68, -122.9), + new ParseGeoPoint(37.68, -122.33), ]; const q = new ParseQuery('Location'); q.withinPolygon('location', points); @@ -675,9 +693,25 @@ describe('OfflineQuery', () => { }); it('should support polygonContains query', () => { - const p1 = [[0,0], [0,1], [1,1], [1,0]]; - const p2 = [[0,0], [0,2], [2,2], [2,0]]; - const p3 = [[10,10], [10,15], [15,15], [15,10], [10,10]]; + const p1 = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + ]; + const p2 = [ + [0, 0], + [0, 2], + [2, 2], + [2, 0], + ]; + const p3 = [ + [10, 10], + [10, 15], + [15, 15], + [15, 10], + [10, 10], + ]; const polygon1 = new ParsePolygon(p1); const polygon2 = new ParsePolygon(p2); diff --git a/src/__tests__/Parse-test.js b/src/__tests__/Parse-test.js index 97256cdd6..d78d53acd 100644 --- a/src/__tests__/Parse-test.js +++ b/src/__tests__/Parse-test.js @@ -79,11 +79,11 @@ describe('Parse module', () => { it('can set LocalDatastoreController', () => { const controller = { - fromPinWithName: function() {}, - pinWithName: function() {}, - unPinWithName: function() {}, - getAllContents: function() {}, - clear: function() {} + fromPinWithName: function () {}, + pinWithName: function () {}, + unPinWithName: function () {}, + getAllContents: function () {}, + clear: function () {}, }; Parse.setLocalDatastoreController(controller); expect(CoreManager.getLocalDatastoreController()).toBe(controller); @@ -91,13 +91,13 @@ describe('Parse module', () => { it('can set AsyncStorage', () => { const controller = { - getItem: function() {}, - setItem: function() {}, - removeItem: function() {}, - getItemAsync: function() {}, - setItemAsync: function() {}, - removeItemAsync: function() {}, - clear: function() {}, + getItem: function () {}, + setItem: function () {}, + removeItem: function () {}, + getItemAsync: function () {}, + setItemAsync: function () {}, + removeItemAsync: function () {}, + clear: function () {}, }; Parse.setAsyncStorage(controller); @@ -118,13 +118,13 @@ describe('Parse module', () => { expect(LDS).toEqual({}); Parse.LocalDatastore.isEnabled = true; const controller = { - fromPinWithName: function() {}, - pinWithName: function() {}, - unPinWithName: function() {}, - getAllContents: function() { + fromPinWithName: function () {}, + pinWithName: function () {}, + unPinWithName: function () {}, + getAllContents: function () { return Promise.resolve({ key: 'value' }); }, - clear: function() {} + clear: function () {}, }; Parse.setLocalDatastoreController(controller); LDS = await Parse.dumpLocalDatastore(); diff --git a/src/__tests__/ParseACL-test.js b/src/__tests__/ParseACL-test.js index d9935dd5d..e7ce0d101 100644 --- a/src/__tests__/ParseACL-test.js +++ b/src/__tests__/ParseACL-test.js @@ -9,12 +9,12 @@ jest.dontMock('../ParseACL'); -const mockRole = function(name) { +const mockRole = function (name) { this.name = name; }; -mockRole.prototype.getName = function() { +mockRole.prototype.getName = function () { return this.name; -} +}; jest.setMock('../ParseRole', mockRole); const ParseACL = require('../ParseACL').default; @@ -39,70 +39,58 @@ describe('ParseACL', () => { expect(a.permissionsById).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); it('throws when constructed with an invalid permissions map', () => { - let err = function() { + let err = function () { new ParseACL({ aUserId: { foo: true, bar: false } }); }; - expect(err).toThrow( - 'Tried to create an ACL with an invalid permission type.' - ); - err = function() { + expect(err).toThrow('Tried to create an ACL with an invalid permission type.'); + err = function () { new ParseACL({ aUserId: { read: 12 } }); }; - expect(err).toThrow( - 'Tried to create an ACL with an invalid permission value.' - ); + expect(err).toThrow('Tried to create an ACL with an invalid permission value.'); }); it('throws a helpful error when constructed with a function', () => { - expect(function() { - new ParseACL(function() { }); + expect(function () { + new ParseACL(function () {}); }).toThrow('ParseACL constructed with a function. Did you forget ()?'); }); it('throws when setting an invalid user id', () => { const a = new ParseACL(); - expect(a.setReadAccess.bind(a, 12, true)).toThrow( - 'userId must be a string.' - ); + expect(a.setReadAccess.bind(a, 12, true)).toThrow('userId must be a string.'); expect(() => { - a.getReadAccess(new ParseUser(), true) + a.getReadAccess(new ParseUser(), true); }).toThrow('Cannot get access for a ParseUser without an ID'); }); it('throws when setting an invalid access', () => { const a = new ParseACL(); - expect(a.setReadAccess.bind(a, 'aUserId', 12)).toThrow( - 'allowed must be either true or false.' - ); + expect(a.setReadAccess.bind(a, 'aUserId', 12)).toThrow('allowed must be either true or false.'); }); it('throws when role does not have name', () => { const a = new ParseACL(); expect(() => { - a.setReadAccess(new ParseRole(), true) + a.setReadAccess(new ParseRole(), true); }).toThrow('Role must have a name'); expect(() => { - a.getReadAccess(new ParseRole(), true) + a.getReadAccess(new ParseRole(), true); }).toThrow('Role must have a name'); }); it('throws when setting an invalid role', () => { const a = new ParseACL(); - expect(a.setRoleReadAccess.bind(a, 12, true)).toThrow( - 'role must be a ParseRole or a String' - ); + expect(a.setRoleReadAccess.bind(a, 12, true)).toThrow('role must be a ParseRole or a String'); - expect(a.setRoleWriteAccess.bind(a, 12, true)).toThrow( - 'role must be a ParseRole or a String' - ); + expect(a.setRoleWriteAccess.bind(a, 12, true)).toThrow('role must be a ParseRole or a String'); }); it('can be rendered to JSON format', () => { @@ -110,8 +98,8 @@ describe('ParseACL', () => { expect(a.toJSON()).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); @@ -126,8 +114,8 @@ describe('ParseACL', () => { a.setReadAccess('aUserId', true); expect(a.permissionsById).toEqual({ aUserId: { - read: true - } + read: true, + }, }); a.setReadAccess('aUserId', false); @@ -138,8 +126,8 @@ describe('ParseACL', () => { const a = new ParseACL({ aUserId: { read: true, - write: false - } + write: false, + }, }); expect(a.getReadAccess('aUserId')).toBe(true); @@ -162,8 +150,8 @@ describe('ParseACL', () => { a.setWriteAccess('aUserId', true); expect(a.permissionsById).toEqual({ aUserId: { - write: true - } + write: true, + }, }); a.setWriteAccess('aUserId', false); @@ -172,8 +160,8 @@ describe('ParseACL', () => { a.setWriteAccess(u, true); expect(a.permissionsById).toEqual({ aUserId: { - write: true - } + write: true, + }, }); a.setWriteAccess(u, false); @@ -184,8 +172,8 @@ describe('ParseACL', () => { const a = new ParseACL({ aUserId: { read: true, - write: false - } + write: false, + }, }); const u = new ParseUser(); @@ -203,8 +191,8 @@ describe('ParseACL', () => { a.setPublicReadAccess(true); expect(a.permissionsById).toEqual({ '*': { - read: true - } + read: true, + }, }); expect(a.getPublicReadAccess()).toBe(true); @@ -220,8 +208,8 @@ describe('ParseACL', () => { a.setPublicWriteAccess(true); expect(a.permissionsById).toEqual({ '*': { - write: true - } + write: true, + }, }); expect(a.getPublicWriteAccess()).toBe(true); @@ -233,8 +221,8 @@ describe('ParseACL', () => { const a = new ParseACL({ 'role:admin': { read: true, - write: true - } + write: true, + }, }); expect(a.getRoleReadAccess('admin')).toBe(true); @@ -246,8 +234,8 @@ describe('ParseACL', () => { const a = new ParseACL({ 'role:admin': { read: true, - write: true - } + write: true, + }, }); expect(a.getRoleWriteAccess('admin')).toBe(true); @@ -257,12 +245,8 @@ describe('ParseACL', () => { it('throws when fetching an invalid role', () => { const a = new ParseACL(); - expect(a.getRoleReadAccess.bind(null, 5)).toThrow( - 'role must be a ParseRole or a String' - ); - expect(a.getRoleWriteAccess.bind(null, 5)).toThrow( - 'role must be a ParseRole or a String' - ); + expect(a.getRoleReadAccess.bind(null, 5)).toThrow('role must be a ParseRole or a String'); + expect(a.getRoleWriteAccess.bind(null, 5)).toThrow('role must be a ParseRole or a String'); }); it('can set role read access', () => { diff --git a/src/__tests__/ParseConfig-test.js b/src/__tests__/ParseConfig-test.js index a468697d1..4e5d96306 100644 --- a/src/__tests__/ParseConfig-test.js +++ b/src/__tests__/ParseConfig-test.js @@ -38,7 +38,7 @@ describe('ParseConfig', () => { const c = new ParseConfig(); c.attributes = { str: 'hello', - num: 44 + num: 44, }; expect(c.get('str')).toBe('hello'); expect(c.get('num')).toBe(44); @@ -49,7 +49,7 @@ describe('ParseConfig', () => { const c = new ParseConfig(); c.attributes = { brackets: '<>', - phone: 'AT&T' + phone: 'AT&T', }; expect(c.escape('brackets')).toBe('<>'); expect(c.escape('phone')).toBe('AT&T'); @@ -58,21 +58,24 @@ describe('ParseConfig', () => { it('can retrieve the current config from disk or cache', () => { const path = Storage.generatePath('currentConfig'); - Storage.setItem(path, JSON.stringify({ - count: 12, - point: { - __type: 'GeoPoint', - latitude: 20.02, - longitude: 30.03 - } - })); + Storage.setItem( + path, + JSON.stringify({ + count: 12, + point: { + __type: 'GeoPoint', + latitude: 20.02, + longitude: 30.03, + }, + }) + ); expect(ParseConfig.current().attributes).toEqual({ count: 12, - point: new ParseGeoPoint(20.02, 30.03) + point: new ParseGeoPoint(20.02, 30.03), }); expect(ParseConfig.current().attributes).toEqual({ count: 12, - point: new ParseGeoPoint(20.02, 30.03) + point: new ParseGeoPoint(20.02, 30.03), }); }); @@ -90,23 +93,26 @@ describe('ParseConfig', () => { const currentStorage = CoreManager.getStorageController(); CoreManager.setStorageController(mockAsyncStorage); const path = Storage.generatePath('currentConfig'); - await Storage.setItemAsync(path, JSON.stringify({ - count: 12, - point: { - __type: 'GeoPoint', - latitude: 20.02, - longitude: 30.03 - } - })); + await Storage.setItemAsync( + path, + JSON.stringify({ + count: 12, + point: { + __type: 'GeoPoint', + latitude: 20.02, + longitude: 30.03, + }, + }) + ); const config = await ParseConfig.current(); expect(config.attributes).toEqual({ count: 12, - point: new ParseGeoPoint(20.02, 30.03) + point: new ParseGeoPoint(20.02, 30.03), }); CoreManager.setStorageController(currentStorage); }); - it('can get a config object from the network', (done) => { + it('can get a config object from the network', done => { CoreManager.setRESTController({ request() { return Promise.resolve({ @@ -116,14 +122,14 @@ describe('ParseConfig', () => { file: { __type: 'File', name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' - } - } + url: 'https://files.parsetfss.com/a/parse.txt', + }, + }, }); }, - ajax() {} + ajax() {}, }); - ParseConfig.get().then((config) => { + ParseConfig.get().then(config => { expect(config.get('str')).toBe('hello'); expect(config.get('num')).toBe(45); expect(config.get('file').name()).toBe('parse.txt'); @@ -134,35 +140,35 @@ describe('ParseConfig', () => { file: { __type: 'File', name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' - } + url: 'https://files.parsetfss.com/a/parse.txt', + }, }); done(); }); }); - it('can save a config object with masterkey', (done) => { + it('can save a config object with masterkey', done => { //Load a request that match the get() & save() request CoreManager.setRESTController({ request() { return Promise.resolve({ - params : { - str : 'hello2', - num : 46 + params: { + str: 'hello2', + num: 46, }, - result: true + result: true, }); }, - ajax() {} + ajax() {}, }); - ParseConfig.save({str: 'hello2','num':46}).then((config) => { + ParseConfig.save({ str: 'hello2', num: 46 }).then(config => { expect(config.get('str')).toBe('hello2'); expect(config.get('num')).toBe(46); const path = Storage.generatePath('currentConfig'); expect(JSON.parse(Storage.getItem(path))).toEqual({ str: 'hello2', - num: 46 + num: 46, }); done(); }); @@ -182,7 +188,7 @@ describe('ParseConfig', () => { return Promise.resolve({ params: { internal: 'i', - number: 12 + number: 12, }, result: true, }); @@ -194,17 +200,14 @@ describe('ParseConfig', () => { return Promise.resolve({ params: { internal: 'i', - number: 12 + number: 12, }, }); } }, - ajax() {} + ajax() {}, }); - const config = await ParseConfig.save( - { internal: 'i', number: 12 }, - { internal: true } - ); + const config = await ParseConfig.save({ internal: 'i', number: 12 }, { internal: true }); expect(config.get('internal')).toBe('i'); expect(config.get('number')).toBe(12); }); @@ -219,11 +222,11 @@ describe('ParseConfig', () => { return Promise.resolve({ params: { str: 'hello', - num: 45 - } + num: 45, + }, }); }, - ajax() {} + ajax() {}, }); const config = await ParseConfig.get({ useMasterKey: true }); expect(config.get('str')).toBe('hello'); @@ -235,44 +238,47 @@ describe('ParseConfig', () => { }); }); - it('rejects save on invalid response', (done) => { + it('rejects save on invalid response', done => { CoreManager.setRESTController({ request() { - return Promise.resolve({result: false}); + return Promise.resolve({ result: false }); }, - ajax() {} - }); - ParseConfig.save({str: 'hello2','num':46}).then((config) => { - expect(config).toBe(1) - done(); - },(error) => { - expect(error.code).toBe(1) - done(); + ajax() {}, }); + ParseConfig.save({ str: 'hello2', num: 46 }).then( + config => { + expect(config).toBe(1); + done(); + }, + error => { + expect(error.code).toBe(1); + done(); + } + ); }); - it('rejects the promise when an invalid payload comes back', (done) => { + it('rejects the promise when an invalid payload comes back', done => { CoreManager.setRESTController({ request() { return Promise.resolve(null); }, - ajax() {} + ajax() {}, }); - ParseConfig.get().then(null, (error) => { + ParseConfig.get().then(null, error => { expect(error.code).toBe(107); expect(error.message).toBe('Config JSON response invalid.'); done(); }); }); - it('rejects the promise when the http request fails', (done) => { + it('rejects the promise when the http request fails', done => { CoreManager.setRESTController({ request() { return Promise.reject('failure'); }, - ajax() {} + ajax() {}, }); - ParseConfig.get().then(null, (error) => { + ParseConfig.get().then(null, error => { expect(error).toBe('failure'); done(); }); diff --git a/src/__tests__/ParseFile-test.js b/src/__tests__/ParseFile-test.js index e1c41613a..afa210baf 100644 --- a/src/__tests__/ParseFile-test.js +++ b/src/__tests__/ParseFile-test.js @@ -30,7 +30,7 @@ const mockLocalDatastore = { jest.setMock('../LocalDatastore', mockLocalDatastore); function generateSaveMock(prefix) { - return function(name, payload, options) { + return function (name, payload, options) { if (options && typeof options.progress === 'function') { options.progress(0.5, 5, 10, { type: 'upload' }); } @@ -48,10 +48,11 @@ describe('ParseFile', () => { CoreManager.setFileController({ saveFile: generateSaveMock('http://files.parsetfss.com/a/'), saveBase64: generateSaveMock('http://files.parsetfss.com/a/'), - download: () => Promise.resolve({ - base64: 'ParseA==', - contentType: 'image/png', - }), + download: () => + Promise.resolve({ + base64: 'ParseA==', + contentType: 'image/png', + }), }); }); @@ -67,21 +68,23 @@ describe('ParseFile', () => { it('can extract data type from base64', () => { const file = new ParseFile('parse.txt', { - base64: 'data:image/png;base64,ParseA==' + base64: 'data:image/png;base64,ParseA==', }); expect(file._source.base64).toBe('ParseA=='); expect(file._source.type).toBe('image/png'); }); it('can create files with file uri', () => { - const file = new ParseFile('parse-image', { uri:'http://example.com/image.png' }); + const file = new ParseFile('parse-image', { + uri: 'http://example.com/image.png', + }); expect(file._source.format).toBe('uri'); expect(file._source.uri).toBe('http://example.com/image.png'); }); it('can extract data type from base64 with data type containing a number', () => { const file = new ParseFile('parse.m4a', { - base64: 'data:audio/m4a;base64,ParseA==' + base64: 'data:audio/m4a;base64,ParseA==', }); expect(file._source.base64).toBe('ParseA=='); expect(file._source.type).toBe('audio/m4a'); @@ -89,7 +92,7 @@ describe('ParseFile', () => { it('can extract data type from base64 with a complex mime type', () => { const file = new ParseFile('parse.kml', { - base64: 'data:application/vnd.google-earth.kml+xml;base64,ParseA==' + base64: 'data:application/vnd.google-earth.kml+xml;base64,ParseA==', }); expect(file._source.base64).toBe('ParseA=='); expect(file._source.type).toBe('application/vnd.google-earth.kml+xml'); @@ -97,7 +100,7 @@ describe('ParseFile', () => { it('can extract data type from base64 with a charset param', () => { const file = new ParseFile('parse.kml', { - base64: 'data:application/vnd.3gpp.pic-bw-var;charset=utf-8;base64,ParseA==' + base64: 'data:application/vnd.3gpp.pic-bw-var;charset=utf-8;base64,ParseA==', }); expect(file._source.base64).toBe('ParseA=='); expect(file._source.type).toBe('application/vnd.3gpp.pic-bw-var'); @@ -122,31 +125,30 @@ describe('ParseFile', () => { }); it('throws when creating a file with invalid data', () => { - expect(function() { + expect(function () { new ParseFile('parse.txt', 12); }).toThrow('Cannot create a Parse.File with that data.'); - expect(function() { + expect(function () { new ParseFile('parse.txt', null); }).toThrow('Cannot create a Parse.File with that data.'); - expect(function() { + expect(function () { new ParseFile('parse.txt', 'string'); }).toThrow('Cannot create a Parse.File with that data.'); }); it('throws with invalid base64', () => { - expect(function() { + expect(function () { b64Digit(65); }).toThrow('Tried to encode large digit 65 in base64.'); }); it('returns secure url when specified', () => { const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); - return file.save().then(function(result) { + return file.save().then(function (result) { expect(result).toBe(file); - expect(result.url({ forceSecure: true })) - .toBe('https://files.parsetfss.com/a/parse.txt'); + expect(result.url({ forceSecure: true })).toBe('https://files.parsetfss.com/a/parse.txt'); }); }); @@ -159,7 +161,7 @@ describe('ParseFile', () => { const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); expect(file.name()).toBe('parse.txt'); expect(file.url()).toBe(undefined); - return file.save().then(function(result) { + return file.save().then(function (result) { expect(result).toBe(file); expect(result.name()).toBe('parse.txt'); expect(result.url()).toBe('http://files.parsetfss.com/a/parse.txt'); @@ -167,10 +169,12 @@ describe('ParseFile', () => { }); it('updates fields when saved with uri', () => { - const file = new ParseFile('parse.png', { uri: 'https://example.com/image.png' }); + const file = new ParseFile('parse.png', { + uri: 'https://example.com/image.png', + }); expect(file.name()).toBe('parse.png'); expect(file.url()).toBe(undefined); - return file.save().then(function(result) { + return file.save().then(function (result) { expect(result).toBe(file); expect(result.name()).toBe('parse.png'); expect(result.url()).toBe('http://files.parsetfss.com/a/parse.png'); @@ -179,11 +183,11 @@ describe('ParseFile', () => { it('generates a JSON representation', () => { const file = new ParseFile('parse.txt', { base64: 'ParseA==' }); - return file.save().then(function(result) { + return file.save().then(function (result) { expect(result.toJSON()).toEqual({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); }); }); @@ -192,14 +196,13 @@ describe('ParseFile', () => { const f = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); expect(f).toBeTruthy(); expect(f.name()).toBe('parse.txt'); expect(f.url()).toBe('http://files.parsetfss.com/a/parse.txt'); - expect(ParseFile.fromJSON.bind(null, {})) - .toThrow('JSON object does not represent a ParseFile'); + expect(ParseFile.fromJSON.bind(null, {})).toThrow('JSON object does not represent a ParseFile'); }); it('can test equality against another ParseFile', () => { @@ -214,12 +217,12 @@ describe('ParseFile', () => { a = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); b = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); expect(a.equals(b)).toBe(true); @@ -228,7 +231,7 @@ describe('ParseFile', () => { b = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/b/parse.txt' + url: 'http://files.parsetfss.com/b/parse.txt', }); expect(a.equals(b)).toBe(false); @@ -236,15 +239,17 @@ describe('ParseFile', () => { }); it('reports progress during save when source is a File', () => { - const file = new ParseFile('progress.txt', new File(["Parse"], "progress.txt")); + const file = new ParseFile('progress.txt', new File(['Parse'], 'progress.txt')); const options = { - progress: function(){} + progress: function () {}, }; jest.spyOn(options, 'progress'); - return file.save(options).then(function(f) { - expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { type: 'upload' }); + return file.save(options).then(function (f) { + expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { + type: 'upload', + }); expect(f).toBe(file); expect(f.name()).toBe('progress.txt'); expect(f.url()).toBe('http://files.parsetfss.com/a/progress.txt'); @@ -256,14 +261,14 @@ describe('ParseFile', () => { abort: () => {}, }; CoreManager.setFileController({ - saveFile: function(name, payload, options) { + saveFile: function (name, payload, options) { options.requestTask(mockRequestTask); return Promise.resolve({}); }, saveBase64: () => {}, download: () => {}, }); - const file = new ParseFile('progress.txt', new File(["Parse"], "progress.txt")); + const file = new ParseFile('progress.txt', new File(['Parse'], 'progress.txt')); jest.spyOn(mockRequestTask, 'abort'); file.cancel(); @@ -292,13 +297,13 @@ describe('ParseFile', () => { { file: expect.any(File), format: 'file', - type: '' + type: '', }, { metadata: { foo: 'bar' }, tags: { bar: 'foo' }, requestTask: expect.any(Function), - }, + } ); }); @@ -352,20 +357,20 @@ describe('ParseFile', () => { describe('FileController', () => { beforeEach(() => { CoreManager.setFileController(defaultController); - const request = function(method, path) { + const request = function (method, path) { const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ name: name, - url: 'https://files.parsetfss.com/a/' + name + url: 'https://files.parsetfss.com/a/' + name, }); }; - const ajax = function(method, path) { + const ajax = function (method, path) { const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ response: { name: name, - url: 'https://files.parsetfss.com/a/' + name - } + url: 'https://files.parsetfss.com/a/' + name, + }, }); }; CoreManager.setRESTController({ request: request, ajax: ajax }); @@ -373,7 +378,7 @@ describe('FileController', () => { it('saves files created with bytes', () => { const file = new ParseFile('parse.txt', [61, 170, 236, 120]); - return file.save().then(function(f) { + return file.save().then(function (f) { expect(f).toBe(file); expect(f.name()).toBe('parse.txt'); expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); @@ -386,7 +391,7 @@ describe('FileController', () => { const file = new ParseFile('parse.txt', blob); file._source.format = 'file'; - return file.save().then(function(f) { + return file.save().then(function (f) { expect(f).toBe(file); expect(f.name()).toBe('parse.txt'); expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); @@ -394,17 +399,15 @@ describe('FileController', () => { }); it('saveUri with uri type', async () => { - const file = new ParseFile('parse.png', { uri: 'https://example.com/image.png' }); - const spy = jest.spyOn( - defaultController, - 'download' - ) - .mockImplementationOnce(() => { - return Promise.resolve({ - base64: 'ParseA==', - contentType: 'image/png', - }); + const file = new ParseFile('parse.png', { + uri: 'https://example.com/image.png', + }); + const spy = jest.spyOn(defaultController, 'download').mockImplementationOnce(() => { + return Promise.resolve({ + base64: 'ParseA==', + contentType: 'image/png', }); + }); const spy2 = jest.spyOn(defaultController, 'saveBase64'); await file.save(); @@ -412,21 +415,21 @@ describe('FileController', () => { expect(defaultController.saveBase64).toHaveBeenCalledTimes(1); expect(defaultController.saveBase64.mock.calls[0][0]).toEqual('parse.png'); expect(defaultController.saveBase64.mock.calls[0][1]).toEqual({ - format: 'base64', base64: 'ParseA==', type: 'image/png' + format: 'base64', + base64: 'ParseA==', + type: 'image/png', }); spy.mockRestore(); spy2.mockRestore(); }); it('save with uri download abort', async () => { - const file = new ParseFile('parse.png', { uri: 'https://example.com/image.png' }); - const spy = jest.spyOn( - defaultController, - 'download' - ) - .mockImplementationOnce(() => { - return Promise.resolve({}); - }); + const file = new ParseFile('parse.png', { + uri: 'https://example.com/image.png', + }); + const spy = jest.spyOn(defaultController, 'download').mockImplementationOnce(() => { + return Promise.resolve({}); + }); const spy2 = jest.spyOn(defaultController, 'saveBase64'); await file.save(); @@ -440,19 +443,18 @@ describe('FileController', () => { defaultController._setXHR(null); const mockResponse = Object.create(EventEmitter.prototype); EventEmitter.call(mockResponse); - mockResponse.setEncoding = function() {} + mockResponse.setEncoding = function () {}; mockResponse.headers = { - 'content-type': 'image/png' + 'content-type': 'image/png', }; - const spy = jest.spyOn(mockHttp, 'get') - .mockImplementationOnce((uri, cb) => { - cb(mockResponse); - mockResponse.emit('data', 'base64String'); - mockResponse.emit('end'); - return { - on: function() {} - }; - }); + const spy = jest.spyOn(mockHttp, 'get').mockImplementationOnce((uri, cb) => { + cb(mockResponse); + mockResponse.emit('data', 'base64String'); + mockResponse.emit('end'); + return { + on: function () {}, + }; + }); const data = await defaultController.download('http://example.com/image.png'); expect(data.base64).toBe('base64String'); @@ -468,19 +470,18 @@ describe('FileController', () => { const mockResponse = Object.create(EventEmitter.prototype); EventEmitter.call(mockRequest); EventEmitter.call(mockResponse); - mockResponse.setEncoding = function() {} + mockResponse.setEncoding = function () {}; mockResponse.headers = { - 'content-type': 'image/png' + 'content-type': 'image/png', }; - const spy = jest.spyOn(mockHttp, 'get') - .mockImplementationOnce((uri, cb) => { - cb(mockResponse); - return mockRequest; - }); + const spy = jest.spyOn(mockHttp, 'get').mockImplementationOnce((uri, cb) => { + cb(mockResponse); + return mockRequest; + }); const options = { requestTask: () => {}, }; - defaultController.download('http://example.com/image.png', options).then((data) => { + defaultController.download('http://example.com/image.png', options).then(data => { expect(data).toEqual({}); }); mockRequest.emit('abort'); @@ -491,19 +492,18 @@ describe('FileController', () => { defaultController._setXHR(null); const mockResponse = Object.create(EventEmitter.prototype); EventEmitter.call(mockResponse); - mockResponse.setEncoding = function() {} + mockResponse.setEncoding = function () {}; mockResponse.headers = { - 'content-type': 'image/png' + 'content-type': 'image/png', }; - const spy = jest.spyOn(mockHttps, 'get') - .mockImplementationOnce((uri, cb) => { - cb(mockResponse); - mockResponse.emit('data', 'base64String'); - mockResponse.emit('end'); - return { - on: function() {} - }; - }); + const spy = jest.spyOn(mockHttps, 'get').mockImplementationOnce((uri, cb) => { + cb(mockResponse); + mockResponse.emit('data', 'base64String'); + mockResponse.emit('end'); + return { + on: function () {}, + }; + }); const data = await defaultController.download('https://example.com/image.png'); expect(data.base64).toBe('base64String'); @@ -518,16 +518,16 @@ describe('FileController', () => { return { DONE: 4, open: jest.fn(), - send: jest.fn().mockImplementation(function() { + send: jest.fn().mockImplementation(function () { this.response = [61, 170, 236, 120]; this.readyState = 2; this.onreadystatechange(); this.readyState = 4; this.onreadystatechange(); }), - getResponseHeader: function() { + getResponseHeader: function () { return 'image/png'; - } + }, }; }; defaultController._setXHR(mockXHR); @@ -544,16 +544,16 @@ describe('FileController', () => { return { DONE: 4, open: jest.fn(), - send: jest.fn().mockImplementation(function() { + send: jest.fn().mockImplementation(function () { this.response = undefined; this.readyState = 2; this.onreadystatechange(); this.readyState = 4; this.onreadystatechange(); }), - getResponseHeader: function() { + getResponseHeader: function () { return 'image/png'; - } + }, }; }; defaultController._setXHR(mockXHR); @@ -568,28 +568,28 @@ describe('FileController', () => { const mockXHR = function () { return { open: jest.fn(), - send: jest.fn().mockImplementation(function() { + send: jest.fn().mockImplementation(function () { this.response = [61, 170, 236, 120]; this.readyState = 2; this.onreadystatechange(); }), - getResponseHeader: function() { + getResponseHeader: function () { return 'image/png'; }, - abort: function() { + abort: function () { this.status = 0; this.response = undefined; this.readyState = 4; - this.onreadystatechange() - } + this.onreadystatechange(); + }, }; }; defaultController._setXHR(mockXHR); let _requestTask; const options = { - requestTask: (task) => _requestTask = task, + requestTask: task => (_requestTask = task), }; - defaultController.download('https://example.com/image.png', options).then((data) => { + defaultController.download('https://example.com/image.png', options).then(data => { expect(data).toEqual({}); }); _requestTask.abort(); @@ -599,9 +599,9 @@ describe('FileController', () => { const mockXHR = function () { return { open: jest.fn(), - send: jest.fn().mockImplementation(function() { + send: jest.fn().mockImplementation(function () { this.onerror('error thrown'); - }) + }), }; }; defaultController._setXHR(mockXHR); @@ -645,17 +645,13 @@ describe('FileController', () => { file._data = null; const result = await file.save(); - const spy = jest.spyOn( - defaultController, - 'download' - ) - .mockImplementationOnce((uri, options) => { - options.requestTask(null); - return Promise.resolve({ - base64: 'ParseA==', - contentType: 'image/png', - }); + const spy = jest.spyOn(defaultController, 'download').mockImplementationOnce((uri, options) => { + options.requestTask(null); + return Promise.resolve({ + base64: 'ParseA==', + contentType: 'image/png', }); + }); const data = await result.getData(); expect(defaultController.download).toHaveBeenCalledTimes(1); @@ -664,21 +660,21 @@ describe('FileController', () => { }); it('saves files via ajax with sessionToken option', () => { - const request = function(method, path) { + const request = function (method, path) { const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ name: name, - url: 'https://files.parsetfss.com/a/' + name + url: 'https://files.parsetfss.com/a/' + name, }); }; - const ajax = function(method, path, data, headers) { - expect(headers['X-Parse-Session-Token']).toBe('testing_sessionToken') + const ajax = function (method, path, data, headers) { + expect(headers['X-Parse-Session-Token']).toBe('testing_sessionToken'); const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ response: { name: name, - url: 'https://files.parsetfss.com/a/' + name - } + url: 'https://files.parsetfss.com/a/' + name, + }, }); }; CoreManager.setRESTController({ request, ajax }); @@ -687,7 +683,7 @@ describe('FileController', () => { const file = new ParseFile('parse.txt', blob); file._source.format = 'file'; - return file.save({ sessionToken: 'testing_sessionToken' }).then(function(f) { + return file.save({ sessionToken: 'testing_sessionToken' }).then(function (f) { expect(f).toBe(file); expect(f.name()).toBe('parse.txt'); expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); @@ -700,25 +696,25 @@ describe('FileController', () => { return Promise.resolve({ getSessionToken() { return 'currentUserToken'; - } + }, }); - } + }, }); - const request = function(method, path) { + const request = function (method, path) { const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ name: name, - url: 'https://files.parsetfss.com/a/' + name + url: 'https://files.parsetfss.com/a/' + name, }); }; - const ajax = function(method, path, data, headers) { - expect(headers['X-Parse-Session-Token']).toBe('currentUserToken') + const ajax = function (method, path, data, headers) { + expect(headers['X-Parse-Session-Token']).toBe('currentUserToken'); const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ response: { name: name, - url: 'https://files.parsetfss.com/a/' + name - } + url: 'https://files.parsetfss.com/a/' + name, + }, }); }; CoreManager.setRESTController({ request, ajax }); @@ -727,7 +723,7 @@ describe('FileController', () => { const file = new ParseFile('parse.txt', blob); file._source.format = 'file'; - return file.save().then(function(f) { + return file.save().then(function (f) { expect(f).toBe(file); expect(f.name()).toBe('parse.txt'); expect(f.url()).toBe('https://files.parsetfss.com/a/parse.txt'); @@ -740,25 +736,25 @@ describe('FileController', () => { return Promise.resolve({ getSessionToken() { return 'currentUserToken'; - } + }, }); - } + }, }); const request = jest.fn((method, path) => { const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ name: name, - url: 'https://files.parsetfss.com/a/' + name + url: 'https://files.parsetfss.com/a/' + name, }); }); - const ajax = function(method, path, data, headers, options) { - expect(options.sessionToken).toBe('currentUserToken') + const ajax = function (method, path, data, headers, options) { + expect(options.sessionToken).toBe('currentUserToken'); const name = path.substr(path.indexOf('/') + 1); return Promise.resolve({ response: { name: name, - url: 'https://files.parsetfss.com/a/' + name - } + url: 'https://files.parsetfss.com/a/' + name, + }, }); }; CoreManager.setRESTController({ request, ajax }); @@ -786,7 +782,7 @@ describe('FileController', () => { }, }, }, - { requestTask: expect.any(Function) }, + { requestTask: expect.any(Function) } ); }); @@ -797,10 +793,10 @@ describe('FileController', () => { expect(options.sessionToken).toBe('testToken'); return { name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }; } - return [ { success: { objectId: 'child' } } ]; + return [{ success: { objectId: 'child' } }]; }); CoreManager.setRESTController({ ajax, request }); CoreManager.setLocalDatastore(mockLocalDatastore); @@ -815,7 +811,7 @@ describe('FileController', () => { expect(request).toHaveBeenCalled(); }); - it('should throw error if file deleted without name', async (done) => { + it('should throw error if file deleted without name', async done => { const file = new ParseFile('', [1, 2, 3]); try { await file.destroy(); @@ -832,21 +828,23 @@ describe('FileController', () => { const result = await file.destroy(); expect(result).toEqual(file); expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { - "X-Parse-Application-ID": null, - "X-Parse-Master-Key": null, + 'X-Parse-Application-ID': null, + 'X-Parse-Master-Key': null, }); }); it('should handle delete file error', async () => { const file = new ParseFile('filename', [1, 2, 3]); - const ajax = jest.fn().mockResolvedValueOnce(Promise.reject(new ParseError(403, 'Cannot delete file.'))); + const ajax = jest + .fn() + .mockResolvedValueOnce(Promise.reject(new ParseError(403, 'Cannot delete file.'))); const handleError = jest.fn(); CoreManager.setRESTController({ ajax, request: () => {}, handleError }); const result = await file.destroy(); expect(result).toEqual(file); expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { - "X-Parse-Application-ID": null, - "X-Parse-Master-Key": null, + 'X-Parse-Application-ID': null, + 'X-Parse-Master-Key': null, }); expect(handleError).toHaveBeenCalled(); }); @@ -860,16 +858,15 @@ describe('FileController', () => { const result = await file.destroy(); expect(result).toEqual(file); expect(ajax).toHaveBeenCalledWith('DELETE', 'https://api.parse.com/1/files/filename', '', { - "X-Parse-Application-ID": null, - "X-Parse-Master-Key": null, + 'X-Parse-Application-ID': null, + 'X-Parse-Master-Key': null, }); expect(handleError).not.toHaveBeenCalled(); }); - it('controller saveFile format errors', async () => { try { - await defaultController.saveFile('parse.txt', { format: 'base64'}); + await defaultController.saveFile('parse.txt', { format: 'base64' }); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('saveFile can only be used with File-type sources.'); @@ -878,7 +875,7 @@ describe('FileController', () => { it('controller saveBase64 format errors', async () => { try { - await defaultController.saveBase64('parse.txt', { format: 'file'}); + await defaultController.saveBase64('parse.txt', { format: 'file' }); expect(true).toBe(false); } catch (e) { expect(e.message).toBe('saveBase64 can only be used with Base64-type sources.'); @@ -894,7 +891,7 @@ describe('FileController', () => { } global.FileReader = FileReader; try { - await defaultController.saveFile('parse.txt', { format: 'file'}); + await defaultController.saveFile('parse.txt', { format: 'file' }); expect(true).toBe(false); } catch (e) { expect(e).toBe('Could not load file.'); diff --git a/src/__tests__/ParseGeoPoint-test.js b/src/__tests__/ParseGeoPoint-test.js index 70fae22b1..2f3e65029 100644 --- a/src/__tests__/ParseGeoPoint-test.js +++ b/src/__tests__/ParseGeoPoint-test.js @@ -11,15 +11,15 @@ jest.autoMockOff(); const ParseGeoPoint = require('../ParseGeoPoint').default; global.navigator.geolocation = { - getCurrentPosition: (cb) => { + getCurrentPosition: cb => { return cb({ coords: { latitude: 10, longitude: 20, - } + }, }); - } -} + }, +}; describe('GeoPoint', () => { it('can be constructed from various inputs', () => { @@ -44,13 +44,13 @@ describe('GeoPoint', () => { [ [NaN, NaN], [false, true], - ["29", "10"], - [29, "10"], - ["29", 10], - [["29", "10"]], - [{ latitude: "29", longitude: "10" }], + ['29', '10'], + [29, '10'], + ['29', 10], + [['29', '10']], + [{ latitude: '29', longitude: '10' }], ].forEach(case_test => { - expect(function() { + expect(function () { new ParseGeoPoint(...case_test); }).toThrow('GeoPoint latitude and longitude must be valid numbers'); }); @@ -151,7 +151,7 @@ describe('GeoPoint', () => { it('can calculate distances in mi and km', () => { // [SAC] 38.52 -121.50 Sacramento,CA - const sacramento = new ParseGeoPoint(38.52, -121.50); + const sacramento = new ParseGeoPoint(38.52, -121.5); // [HNL] 21.35 -157.93 Honolulu Int,HI const honolulu = new ParseGeoPoint(21.35, -157.93); @@ -163,16 +163,16 @@ describe('GeoPoint', () => { const vorkuta = new ParseGeoPoint(67.509619, 64.085999); // London - const london = new ParseGeoPoint(51.501904,-0.115356); + const london = new ParseGeoPoint(51.501904, -0.115356); // Northampton - const northampton = new ParseGeoPoint(52.241256,-0.895386); + const northampton = new ParseGeoPoint(52.241256, -0.895386); // Powell St BART station - const powell = new ParseGeoPoint(37.785071,-122.407007); + const powell = new ParseGeoPoint(37.785071, -122.407007); // Apple store - const astore = new ParseGeoPoint(37.785809,-122.406363); + const astore = new ParseGeoPoint(37.785809, -122.406363); // Self expect(honolulu.kilometersTo(honolulu)).toBeCloseTo(0.0, 3); diff --git a/src/__tests__/ParseInstallation-test.js b/src/__tests__/ParseInstallation-test.js index ce1b6853d..20c01d007 100644 --- a/src/__tests__/ParseInstallation-test.js +++ b/src/__tests__/ParseInstallation-test.js @@ -22,7 +22,7 @@ describe('ParseInstallation', () => { expect(installation.get('deviceToken')).toBe('token'); expect(() => { - new ParseInstallation({ 'invalid#name' : 'foo'}) + new ParseInstallation({ 'invalid#name': 'foo' }); }).toThrow("Can't create an invalid Installation"); }); }); diff --git a/src/__tests__/ParseLiveQuery-test.js b/src/__tests__/ParseLiveQuery-test.js index 366ced8f8..7f4a52643 100644 --- a/src/__tests__/ParseLiveQuery-test.js +++ b/src/__tests__/ParseLiveQuery-test.js @@ -34,19 +34,19 @@ describe('ParseLiveQuery', () => { CoreManager.set('InstallationController', { currentInstallationId() { return Promise.resolve('1234'); - } + }, }); }); - it('fails with an invalid livequery server url', (done) => { + it('fails with an invalid livequery server url', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(undefined); - } + }, }); CoreManager.set('LIVEQUERY_SERVER_URL', 'notaurl'); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().catch((err) => { + controller.getDefaultLiveQueryClient().catch(err => { expect(err.message).toBe( 'You need to set a proper Parse LiveQuery server url before using LiveQueryClient' ); @@ -54,17 +54,17 @@ describe('ParseLiveQuery', () => { }); }); - it('initializes the client', (done) => { + it('initializes the client', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(undefined); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); CoreManager.set('LIVEQUERY_SERVER_URL', 'wss://live.example.com/parse'); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then((client) => { + controller.getDefaultLiveQueryClient().then(client => { expect(client.serverURL).toBe('wss://live.example.com/parse'); expect(client.applicationId).toBe('appid'); expect(client.javascriptKey).toBe('jskey'); @@ -75,18 +75,18 @@ describe('ParseLiveQuery', () => { }); }); - it('automatically generates a ws websocket url', (done) => { + it('automatically generates a ws websocket url', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(undefined); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); CoreManager.set('SERVER_URL', 'http://api.parse.com/1'); CoreManager.set('LIVEQUERY_SERVER_URL', null); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then((client) => { + controller.getDefaultLiveQueryClient().then(client => { expect(client.serverURL).toBe('ws://api.parse.com/1'); expect(client.applicationId).toBe('appid'); expect(client.javascriptKey).toBe('jskey'); @@ -95,18 +95,18 @@ describe('ParseLiveQuery', () => { }); }); - it('automatically generates a wss websocket url', (done) => { + it('automatically generates a wss websocket url', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(undefined); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); CoreManager.set('SERVER_URL', 'https://api.parse.com/1'); CoreManager.set('LIVEQUERY_SERVER_URL', null); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then((client) => { + controller.getDefaultLiveQueryClient().then(client => { expect(client.serverURL).toBe('wss://api.parse.com/1'); expect(client.applicationId).toBe('appid'); expect(client.javascriptKey).toBe('jskey'); @@ -115,21 +115,21 @@ describe('ParseLiveQuery', () => { }); }); - it('populates the session token', (done) => { + it('populates the session token', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); CoreManager.set('LIVEQUERY_SERVER_URL', null); const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then((client) => { + controller.getDefaultLiveQueryClient().then(client => { expect(client.serverURL).toBe('wss://api.parse.com/1'); expect(client.applicationId).toBe('appid'); expect(client.javascriptKey).toBe('jskey'); @@ -146,9 +146,9 @@ describe('ParseLiveQuery', () => { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); @@ -164,15 +164,15 @@ describe('ParseLiveQuery', () => { spy.mockRestore(); }); - it('subscribes to all subscription events', (done) => { + it('subscribes to all subscription events', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); CoreManager.set('APPLICATION_ID', 'appid'); CoreManager.set('JAVASCRIPT_KEY', 'jskey'); @@ -180,21 +180,13 @@ describe('ParseLiveQuery', () => { const controller = CoreManager.getLiveQueryController(); - controller.getDefaultLiveQueryClient().then(async (client) => { - - const query = new ParseQuery("ObjectType"); - query.equalTo("test", "value"); - const ourSubscription = await client.subscribe(query, "close"); + controller.getDefaultLiveQueryClient().then(async client => { + const query = new ParseQuery('ObjectType'); + query.equalTo('test', 'value'); + const ourSubscription = await client.subscribe(query, 'close'); const isCalled = {}; - ["open", - "close", - "error", - "create", - "update", - "enter", - "leave", - "delete"].forEach((key) =>{ + ['open', 'close', 'error', 'create', 'update', 'enter', 'leave', 'delete'].forEach(key => { ourSubscription.on(key, () => { isCalled[key] = true; }); @@ -205,57 +197,57 @@ describe('ParseLiveQuery', () => { setTimeout(() => { try { client.socket = { - send() {} - } + send() {}, + }; client.connectPromise.resolve(); const actualSubscription = client.subscriptions.get(1); expect(actualSubscription).toBeDefined(); - actualSubscription.emit("open"); - expect(isCalled["open"]).toBe(true); + actualSubscription.emit('open'); + expect(isCalled['open']).toBe(true); - actualSubscription.emit("close"); - expect(isCalled["close"]).toBe(true); + actualSubscription.emit('close'); + expect(isCalled['close']).toBe(true); - actualSubscription.emit("error"); - expect(isCalled["error"]).toBe(true); + actualSubscription.emit('error'); + expect(isCalled['error']).toBe(true); - actualSubscription.emit("create"); - expect(isCalled["create"]).toBe(true); + actualSubscription.emit('create'); + expect(isCalled['create']).toBe(true); - actualSubscription.emit("update"); - expect(isCalled["update"]).toBe(true); + actualSubscription.emit('update'); + expect(isCalled['update']).toBe(true); - actualSubscription.emit("enter"); - expect(isCalled["enter"]).toBe(true); + actualSubscription.emit('enter'); + expect(isCalled['enter']).toBe(true); - actualSubscription.emit("leave"); - expect(isCalled["leave"]).toBe(true); + actualSubscription.emit('leave'); + expect(isCalled['leave']).toBe(true); - actualSubscription.emit("delete"); - expect(isCalled["delete"]).toBe(true); + actualSubscription.emit('delete'); + expect(isCalled['delete']).toBe(true); done(); - } catch(e){ + } catch (e) { done.fail(e); } }, 1); }); }); - it('should not throw on usubscribe', (done) => { + it('should not throw on usubscribe', done => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); - const query = new ParseQuery("ObjectType"); - query.equalTo("test", "value"); + const query = new ParseQuery('ObjectType'); + query.equalTo('test', 'value'); const subscription = new LiveQuerySubscription('0', query, 'token'); subscription.unsubscribe().then(done).catch(done.fail); }); diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 8118552c5..892e6fb11 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -41,7 +41,7 @@ jest.dontMock('./test_helpers/mockXHR'); jest.useFakeTimers(); -const mockRelation = function(parent, key) { +const mockRelation = function (parent, key) { // The parent and key fields will be populated by the parent if (parent) { this.parentClass = parent.className; @@ -49,33 +49,27 @@ const mockRelation = function(parent, key) { } this.key = key; }; -mockRelation.prototype.add = function(obj) { +mockRelation.prototype.add = function (obj) { this.targetClassName = obj.className; }; -mockRelation.prototype.toJSON = function() { +mockRelation.prototype.toJSON = function () { return { __type: 'Relation', - className: this.targetClassName + className: this.targetClassName, }; }; -mockRelation.prototype._ensureParentAndKey = function(parent, key) { +mockRelation.prototype._ensureParentAndKey = function (parent, key) { this.key = this.key || key; if (this.key !== key) { - throw new Error( - 'Internal Error. Relation retrieved from two different keys.' - ); + throw new Error('Internal Error. Relation retrieved from two different keys.'); } if (this.parent) { if (this.parent.className !== parent.className) { - throw new Error( - 'Internal Error. Relation retrieved from two different Objects.' - ); + throw new Error('Internal Error. Relation retrieved from two different Objects.'); } if (this.parent.id) { if (this.parent.id !== parent.id) { - throw new Error( - 'Internal Error. Relation retrieved from two different Objects.' - ); + throw new Error('Internal Error. Relation retrieved from two different Objects.'); } } else if (parent.id) { this.parent = parent; @@ -86,30 +80,32 @@ mockRelation.prototype._ensureParentAndKey = function(parent, key) { }; jest.setMock('../ParseRelation', mockRelation); -const mockQuery = function(className) { +const mockQuery = function (className) { this.className = className; }; -mockQuery.prototype.containedIn = function(field, ids) { +mockQuery.prototype.containedIn = function (field, ids) { this.results = []; - ids.forEach((id) => { - this.results.push(ParseObject.fromJSON({ - className: this.className, - objectId: id - })); + ids.forEach(id => { + this.results.push( + ParseObject.fromJSON({ + className: this.className, + objectId: id, + }) + ); }); }; -mockQuery.prototype.include = function(keys) { +mockQuery.prototype.include = function (keys) { this._include = keys; }; -mockQuery.prototype.find = function() { +mockQuery.prototype.find = function () { return Promise.resolve(this.results); }; -mockQuery.prototype.get = function(id) { +mockQuery.prototype.get = function (id) { const object = ParseObject.fromJSON({ className: this.className, - objectId: id + objectId: id, }); return Promise.resolve(object); }; @@ -162,18 +158,14 @@ CoreManager.setRESTController(RESTController); CoreManager.setInstallationController({ currentInstallationId() { return Promise.resolve('iid'); - } + }, }); CoreManager.set('APPLICATION_ID', 'A'); CoreManager.set('JAVASCRIPT_KEY', 'B'); CoreManager.set('MASTER_KEY', 'C'); CoreManager.set('VERSION', 'V'); -const { - SetOp, - UnsetOp, - IncrementOp -} = require('../ParseOp'); +const { SetOp, UnsetOp, IncrementOp } = require('../ParseOp'); function flushPromises() { return new Promise(resolve => setImmediate(resolve)); @@ -195,7 +187,7 @@ describe('ParseObject', () => { it('can be created with initial attributes', () => { const o = new ParseObject({ className: 'Item', - value: 12 + value: 12, }); expect(o.className).toBe('Item'); expect(o.attributes).toEqual({ value: 12 }); @@ -235,7 +227,7 @@ describe('ParseObject', () => { expect(() => { new ParseObject({ className: 'Item', - 'invalid#name' : 'foo', + 'invalid#name': 'foo', }); }).toThrow("Can't create an invalid Parse Object"); }); @@ -249,11 +241,14 @@ describe('ParseObject', () => { } } - const o = new ValidatedObject({ - className: 'Item', - value: 12, - badAttr: true - }, { ignoreValidation: true }); + const o = new ValidatedObject( + { + className: 'Item', + value: 12, + badAttr: true, + }, + { ignoreValidation: true } + ); expect(o.attributes.value).toBe(12); expect(o.attributes.badAttr).toBe(true); @@ -264,7 +259,7 @@ describe('ParseObject', () => { className: 'Item', createdAt: '2013-12-14T04:51:19Z', objectId: 'I1', - size: 'medium' + size: 'medium', }; const o = ParseObject.fromJSON(json); expect(o.className).toBe('Item'); @@ -272,7 +267,7 @@ describe('ParseObject', () => { expect(o.attributes).toEqual({ size: 'medium', createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)) + updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), }); expect(o.dirty()).toBe(false); }); @@ -281,14 +276,17 @@ describe('ParseObject', () => { const o = ParseObject.fromJSON({ className: 'Item', objectId: 'I01', - size: 'small' + size: 'small', }); expect(o.get('size')).toBe('small'); - const o2 = ParseObject.fromJSON({ - className: 'Item', - objectId: 'I01', - disabled: true - }, true); + const o2 = ParseObject.fromJSON( + { + className: 'Item', + objectId: 'I01', + disabled: true, + }, + true + ); expect(o.get('disabled')).toBe(true); expect(o.get('size')).toBe(undefined); expect(o.has('size')).toBe(false); @@ -307,7 +305,9 @@ describe('ParseObject', () => { it('has a read-only attributes property', () => { const o = new ParseObject('Item'); o.set('size', 'small'); - expect(function() { o.attributes.size = 'large'; }).toThrow(); + expect(function () { + o.attributes.size = 'large'; + }).toThrow(); }); it('exposes read-only createdAt and updatedAt', () => { @@ -319,7 +319,7 @@ describe('ParseObject', () => { o._finishFetch({ objectId: 'O1', createdAt: { __type: 'Date', iso: created.toISOString() }, - updatedAt: { __type: 'Date', iso: updated.toISOString() } + updatedAt: { __type: 'Date', iso: updated.toISOString() }, }); expect(o.get('createdAt')).toEqual(created); expect(o.get('updatedAt')).toEqual(updated); @@ -328,11 +328,11 @@ describe('ParseObject', () => { }); it('fetch ACL from serverData', () => { - const ACL = new ParseACL({ 'user1': { read: true } }); + const ACL = new ParseACL({ user1: { read: true } }); const o = new ParseObject('Item'); o._finishFetch({ objectId: 'O1', - ACL: { 'user1': { read: true } }, + ACL: { user1: { read: true } }, }); expect(o.getACL()).toEqual(ACL); }); @@ -341,23 +341,23 @@ describe('ParseObject', () => { let o = new ParseObject('Item'); o.set({ size: 'large', - inStock: 18 + inStock: 18, }); expect(o.toJSON()).toEqual({ size: 'large', - inStock: 18 + inStock: 18, }); o = new ParseObject('Item'); o._finishFetch({ objectId: 'O2', size: 'medium', - inStock: 12 + inStock: 12, }); expect(o.id).toBe('O2'); expect(o.toJSON()).toEqual({ objectId: 'O2', size: 'medium', - inStock: 12 + inStock: 12, }); }); @@ -365,42 +365,48 @@ describe('ParseObject', () => { const o = ParseObject.fromJSON({ id: 'hasDates', className: 'Item', - createdAt: { __type: 'Date', iso: new Date(Date.UTC(2015, 0, 1)).toJSON() }, - updatedAt: { __type: 'Date', iso: new Date(Date.UTC(2015, 0, 1)).toJSON() }, - foo: 'bar' + createdAt: { + __type: 'Date', + iso: new Date(Date.UTC(2015, 0, 1)).toJSON(), + }, + updatedAt: { + __type: 'Date', + iso: new Date(Date.UTC(2015, 0, 1)).toJSON(), + }, + foo: 'bar', }); expect(o.toJSON()).toEqual({ id: 'hasDates', createdAt: '2015-01-01T00:00:00.000Z', updatedAt: '2015-01-01T00:00:00.000Z', - foo: 'bar' + foo: 'bar', }); }); it('can convert to a pointer', () => { const o = new ParseObject('Item'); - expect(function() {o.toPointer();}).toThrow( - 'Cannot create a pointer to an unsaved ParseObject' - ); + expect(function () { + o.toPointer(); + }).toThrow('Cannot create a pointer to an unsaved ParseObject'); o.id = 'anObjectId'; expect(o.toPointer()).toEqual({ __type: 'Pointer', className: 'Item', - objectId: 'anObjectId' + objectId: 'anObjectId', }); }); it('can convert to a offline pointer', () => { const o = new ParseObject('Item'); o.id = 'AnObjectId'; - expect(function() {o.toOfflinePointer();}).toThrow( - 'Cannot create a offline pointer to a saved ParseObject' - ); + expect(function () { + o.toOfflinePointer(); + }).toThrow('Cannot create a offline pointer to a saved ParseObject'); o._localId = 'local1234'; expect(o.toOfflinePointer()).toEqual({ __type: 'Object', className: 'Item', - _localId: 'local1234' + _localId: 'local1234', }); }); @@ -479,7 +485,7 @@ describe('ParseObject', () => { expect(o.dirty('human')).toBe(true); expect(o.dirty('unset')).toBe(false); expect(o.dirty('objectField')).toBe(true); - }) + }); it('can unset a field', () => { const o = new ParseObject('Person'); @@ -496,7 +502,7 @@ describe('ParseObject', () => { const o2 = new ParseObject('Person'); o2._finishFetch({ objectId: 'P1', - name: 'Will' + name: 'Will', }); expect(o2.attributes).toEqual({ name: 'Will' }); o2.unset('name'); @@ -527,21 +533,17 @@ describe('ParseObject', () => { expect(o.op('age') instanceof IncrementOp).toBe(true); expect(o.dirtyKeys()).toEqual(['age']); expect(o._getSaveJSON()).toEqual({ - age: { __op: 'Increment', amount: 1 } + age: { __op: 'Increment', amount: 1 }, }); o.increment('age', 4); expect(o.attributes).toEqual({ age: 5 }); expect(o._getSaveJSON()).toEqual({ - age: { __op: 'Increment', amount: 5 } + age: { __op: 'Increment', amount: 5 }, }); - expect(o.increment.bind(o, 'age', 'four')).toThrow( - 'Cannot increment by a non-numeric amount.' - ); - expect(o.increment.bind(o, 'age', null)).toThrow( - 'Cannot increment by a non-numeric amount.' - ); + expect(o.increment.bind(o, 'age', 'four')).toThrow('Cannot increment by a non-numeric amount.'); + expect(o.increment.bind(o, 'age', null)).toThrow('Cannot increment by a non-numeric amount.'); expect(o.increment.bind(o, 'age', { amount: 4 })).toThrow( 'Cannot increment by a non-numeric amount.' ); @@ -550,20 +552,19 @@ describe('ParseObject', () => { o.increment('age'); expect(o.attributes).toEqual({ age: 31 }); expect(o._getSaveJSON()).toEqual({ - age: 31 + age: 31, }); const o2 = new ParseObject('Person'); o2._finishFetch({ objectId: 'P2', - age: 40 + age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); o2.increment('age'); expect(o2.attributes).toEqual({ age: 41 }); }); - it('can decrement a field', () => { const o = new ParseObject('Person'); o.decrement('age'); @@ -571,21 +572,17 @@ describe('ParseObject', () => { expect(o.op('age') instanceof IncrementOp).toBe(true); expect(o.dirtyKeys()).toEqual(['age']); expect(o._getSaveJSON()).toEqual({ - age: { __op: 'Increment', amount: -1 } + age: { __op: 'Increment', amount: -1 }, }); o.decrement('age', 4); expect(o.attributes).toEqual({ age: -5 }); expect(o._getSaveJSON()).toEqual({ - age: { __op: 'Increment', amount: -5 } + age: { __op: 'Increment', amount: -5 }, }); - expect(o.decrement.bind(o, 'age', 'four')).toThrow( - 'Cannot decrement by a non-numeric amount.' - ); - expect(o.decrement.bind(o, 'age', null)).toThrow( - 'Cannot decrement by a non-numeric amount.' - ); + expect(o.decrement.bind(o, 'age', 'four')).toThrow('Cannot decrement by a non-numeric amount.'); + expect(o.decrement.bind(o, 'age', null)).toThrow('Cannot decrement by a non-numeric amount.'); expect(o.decrement.bind(o, 'age', { amount: 4 })).toThrow( 'Cannot decrement by a non-numeric amount.' ); @@ -594,13 +591,13 @@ describe('ParseObject', () => { o.decrement('age'); expect(o.attributes).toEqual({ age: 29 }); expect(o._getSaveJSON()).toEqual({ - age: 29 + age: 29, }); const o2 = new ParseObject('Person'); o2._finishFetch({ objectId: 'ABC123', - age: 40 + age: 40, }); expect(o2.attributes).toEqual({ age: 40 }); o2.decrement('age'); @@ -613,7 +610,7 @@ describe('ParseObject', () => { objectId: 'setNested', objectField: { number: 5, - letter: 'a' + letter: 'a', }, otherField: {}, }); @@ -643,7 +640,7 @@ describe('ParseObject', () => { objectId: 'incNested', objectField: { number: 5, - letter: 'a' + letter: 'a', }, }); @@ -659,8 +656,8 @@ describe('ParseObject', () => { expect(o.dirtyKeys()).toEqual(['objectField.number', 'objectField']); expect(o._getSaveJSON()).toEqual({ 'objectField.number': { - "__op": "Increment", - "amount": 1 + __op: 'Increment', + amount: 1, }, }); @@ -668,11 +665,11 @@ describe('ParseObject', () => { o._handleSaveResponse({ objectId: 'incNested', objectField: { - number: 6 - } - }) - expect(o.get('objectField').number).toEqual(6) - expect(o.get('objectField').letter).toEqual('a') + number: 6, + }, + }); + expect(o.get('objectField').number).toEqual(6); + expect(o.get('objectField').letter).toEqual('a'); }); it('ignore set nested field on new object', () => { @@ -698,7 +695,7 @@ describe('ParseObject', () => { o._handleSaveResponse({ objectId: 'S1', available: ['Monday', 'Wednesday'], - colors: ['red', 'green', 'blue'] + colors: ['red', 'green', 'blue'], }); o.addUnique('available', 'Thursday'); @@ -718,7 +715,7 @@ describe('ParseObject', () => { o._handleSaveResponse({ objectId: 'S1', available: ['Monday', 'Wednesday'], - colors: ['red', 'green', 'blue'] + colors: ['red', 'green', 'blue'], }); o.addAllUnique('available', ['Thursday', 'Monday']); @@ -734,7 +731,7 @@ describe('ParseObject', () => { o._handleSaveResponse({ objectId: 'S2', - available: ['Monday'] + available: ['Monday'], }); o.remove('available', 'Monday'); @@ -750,7 +747,7 @@ describe('ParseObject', () => { o._handleSaveResponse({ objectId: 'S2', - available: ['Monday'] + available: ['Monday'], }); o.removeAll('available', ['Monday', 'Tuesday']); @@ -762,7 +759,7 @@ describe('ParseObject', () => { o.set('developer', true).set('platform', 'web'); expect(o.attributes).toEqual({ developer: true, - platform: 'web' + platform: 'web', }); }); @@ -778,9 +775,7 @@ describe('ParseObject', () => { const o = new ParseObject('Person'); o.id = 'AA'; o.set('age', 38); - expect(o.relation.bind(o, 'age')).toThrow( - 'Called relation() on non-relation field age' - ); + expect(o.relation.bind(o, 'age')).toThrow('Called relation() on non-relation field age'); const rel = o.relation('friends'); expect(rel.parentClass).toBe('Person'); expect(rel.parentId).toBe('AA'); @@ -792,7 +787,7 @@ describe('ParseObject', () => { }); it('can be cloned with relation (#381)', () => { - const relationJSON = {__type: 'Relation', className: 'Bar'}; + const relationJSON = { __type: 'Relation', className: 'Bar' }; const o = ParseObject.fromJSON({ objectId: '7777777777', className: 'Foo', @@ -803,7 +798,7 @@ describe('ParseObject', () => { }); it('can get relation from relation field', () => { - const relationJSON = {__type: 'Relation', className: 'Bar'}; + const relationJSON = { __type: 'Relation', className: 'Bar' }; const o = ParseObject.fromJSON({ objectId: '999', className: 'Foo', @@ -821,22 +816,22 @@ describe('ParseObject', () => { location: { __type: 'GeoPoint', latitude: 20, - longitude: 20 - } + longitude: 20, + }, }); expect(o.dirty()).toBe(false); o.get('obj').b = 21; expect(o.get('obj')).toEqual({ a: 12, - b: 21 + b: 21, }); expect(o.dirty()).toBe(true); expect(o.dirtyKeys()).toEqual(['obj']); expect(o._getSaveJSON()).toEqual({ obj: { a: 12, - b: 21 - } + b: 21, + }, }); delete o.get('obj').b; expect(o.dirty()).toBe(false); @@ -857,25 +852,29 @@ describe('ParseObject', () => { it('can validate attributes', () => { const o = new ParseObject('Listing'); - expect(o.validate({ - ACL: 'not an acl' - })).toEqual( - new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.') - ); + expect( + o.validate({ + ACL: 'not an acl', + }) + ).toEqual(new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.')); - expect(o.validate({ - 'invalid!key': 12 - })).toEqual( - new ParseError(ParseError.INVALID_KEY_NAME) - ); + expect( + o.validate({ + 'invalid!key': 12, + }) + ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME)); - expect(o.validate({ - noProblem: 'here' - })).toBe(false); + expect( + o.validate({ + noProblem: 'here', + }) + ).toBe(false); - expect(o.validate({ - 'dot.field': 'here' - })).toBe(false); + expect( + o.validate({ + 'dot.field': 'here', + }) + ).toBe(false); }); it('validates attributes on set()', () => { @@ -884,10 +883,12 @@ describe('ParseObject', () => { expect(o.set('ACL', { '*': { read: true, write: false } })).toBe(o); expect(o.set('$$$', 'o_O')).toBe(false); - o.set('$$$', 'o_O', { error: function(obj, err) { - expect(obj).toBe(o); - expect(err.code).toBe(105); - }}); + o.set('$$$', 'o_O', { + error: function (obj, err) { + expect(obj).toBe(o); + expect(err.code).toBe(105); + }, + }); }); it('ignores validation if ignoreValidation option is passed to set()', () => { @@ -904,7 +905,7 @@ describe('ParseObject', () => { expect(o.isValid()).toBe(true); o._finishFetch({ objectId: 'O3', - 'invalid!key': 'oops' + 'invalid!key': 'oops', }); expect(o.isValid()).toBe(false); }); @@ -927,16 +928,16 @@ describe('ParseObject', () => { child: { __type: 'Pointer', className: 'Item', - objectId: 'recurChild' - } + objectId: 'recurChild', + }, }); expect(o.toJSON()).toEqual({ objectId: 'recurParent', child: { __type: 'Pointer', className: 'Item', - objectId: 'recurChild' - } + objectId: 'recurChild', + }, }); ParseObject.fromJSON({ @@ -946,8 +947,8 @@ describe('ParseObject', () => { parent: { __type: 'Pointer', className: 'Item', - objectId: 'recurParent' - } + objectId: 'recurParent', + }, }); expect(o.toJSON()).toEqual({ @@ -959,9 +960,9 @@ describe('ParseObject', () => { parent: { __type: 'Pointer', className: 'Item', - objectId: 'recurParent' - } - } + objectId: 'recurParent', + }, + }, }); }); @@ -974,13 +975,13 @@ describe('ParseObject', () => { updatedAt: '1970-01-01T00:00:00.000Z', aDate: { __type: 'Date', - iso: '1970-01-01T00:00:00.000Z' + iso: '1970-01-01T00:00:00.000Z', }, child: { __type: 'Pointer', className: 'Item', - objectId: 'recurChild' - } + objectId: 'recurChild', + }, }); expect(o.createdAt.getTime()).toBe(new Date(0).getTime()); expect(o.updatedAt.getTime()).toBe(new Date(0).getTime()); @@ -995,8 +996,8 @@ describe('ParseObject', () => { parent: { __type: 'Pointer', className: 'Item', - objectId: 'recurParent' - } + objectId: 'recurParent', + }, }); expect(o.toJSON()).toEqual({ @@ -1005,7 +1006,7 @@ describe('ParseObject', () => { updatedAt: '1970-01-01T00:00:00.000Z', aDate: { __type: 'Date', - iso: '1970-01-01T00:00:00.000Z' + iso: '1970-01-01T00:00:00.000Z', }, child: { __type: 'Object', @@ -1016,9 +1017,9 @@ describe('ParseObject', () => { parent: { __type: 'Pointer', className: 'Item', - objectId: 'recurParent' - } - } + objectId: 'recurParent', + }, + }, }); }); @@ -1030,8 +1031,8 @@ describe('ParseObject', () => { child: { __type: 'Pointer', className: 'Item', - objectId: 'nestedParent' - } + objectId: 'nestedParent', + }, }); const parent = ParseObject.fromJSON({ @@ -1041,15 +1042,15 @@ describe('ParseObject', () => { child: { __type: 'Pointer', className: 'Item', - objectId: 'nestedChild' - } + objectId: 'nestedChild', + }, }); const child = ParseObject.fromJSON({ __type: 'Object', className: 'Item', objectId: 'nestedChild', - count: 12 + count: 12, }); expect(grandparent.get('child').id).toBe(parent.id); @@ -1065,9 +1066,9 @@ describe('ParseObject', () => { __type: 'Object', className: 'Item', objectId: 'nestedChild', - count: 12 - } - } + count: 12, + }, + }, }); }); @@ -1075,9 +1076,12 @@ describe('ParseObject', () => { const o = new ParseObject('Item'); expect(o.existed()).toBe(false); expect(o.isNew()).toBe(true); - o._handleSaveResponse({ - objectId: 'I2' - }, 201); + o._handleSaveResponse( + { + objectId: 'I2', + }, + 201 + ); expect(o.existed()).toBe(false); o._handleSaveResponse({}, 200); expect(o.existed()).toBe(true); @@ -1097,11 +1101,11 @@ describe('ParseObject', () => { expect(p.op('age') instanceof SetOp).toBe(true); const updated = new Date(); p._handleSaveResponse({ - updatedAt: { __type: 'Date', iso: updated.toISOString() } + updatedAt: { __type: 'Date', iso: updated.toISOString() }, }); expect(p._getServerData()).toEqual({ updatedAt: updated, - age: 24 + age: 24, }); expect(p.op('age')).toBe(undefined); }); @@ -1127,7 +1131,13 @@ describe('ParseObject', () => { const p = new ParseObject('Person'); p.id = 'PPolygon'; const created = new Date(); - const polygon = new ParsePolygon([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]); + const polygon = new ParsePolygon([ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]); p._handleSaveResponse({ createdAt: created.toISOString(), shape: polygon.toJSON(), @@ -1145,7 +1155,7 @@ describe('ParseObject', () => { p.id = 'P9'; const created = new Date(); p._handleSaveResponse({ - createdAt: created.toISOString() + createdAt: created.toISOString(), }); expect(p._getServerData()).toEqual({ updatedAt: created, @@ -1160,7 +1170,7 @@ describe('ParseObject', () => { expect(p.isDataAvailable()).toBe(false); const updated = new Date(); p._handleSaveResponse({ - updatedAt: { __type: 'Date', iso: updated.toISOString() } + updatedAt: { __type: 'Date', iso: updated.toISOString() }, }); expect(p.isDataAvailable()).toBe(true); }); @@ -1168,9 +1178,12 @@ describe('ParseObject', () => { it('handles ACL when saved', () => { const p = new ParseObject('Person'); - p._handleSaveResponse({ - ACL: {} - }, 201); + p._handleSaveResponse( + { + ACL: {}, + }, + 201 + ); const acl = p.getACL(); expect(acl).not.toEqual(null); @@ -1182,13 +1195,19 @@ describe('ParseObject', () => { p.set('age', 34); expect(p._localId).toBeTruthy(); expect(p.id).toBe(undefined); - const oldState = SingleInstanceStateController.getState({ className: 'Person', id: p._localId }); + const oldState = SingleInstanceStateController.getState({ + className: 'Person', + id: p._localId, + }); p._handleSaveResponse({ - objectId: 'P4' + objectId: 'P4', }); expect(p._localId).toBe(undefined); expect(p.id).toBe('P4'); - const newState = SingleInstanceStateController.getState({ className: 'Person', id: 'P4' }); + const newState = SingleInstanceStateController.getState({ + className: 'Person', + id: 'P4', + }); expect(oldState.serverData).toBe(newState.serverData); expect(oldState.pendingOps).toBe(newState.pendingOps); expect(oldState.tasks).toBe(newState.tasks); @@ -1198,7 +1217,7 @@ describe('ParseObject', () => { const o = ParseObject.fromJSON({ className: 'Item', objectId: 'iexist', - count: 7 + count: 7, }); expect(o.existed()).toBe(true); }); @@ -1207,7 +1226,7 @@ describe('ParseObject', () => { const o = ParseObject.fromJSON({ className: 'Item', objectId: 'canrevert', - count: 5 + count: 5, }); o.set({ cool: true }); o.increment('count'); @@ -1224,7 +1243,7 @@ describe('ParseObject', () => { const o = ParseObject.fromJSON({ className: 'Item', objectId: 'canrevertspecific', - count: 5 + count: 5, }); o.set({ cool: true }); o.increment('count'); @@ -1243,7 +1262,7 @@ describe('ParseObject', () => { objectId: 'canrevertmultiple', count: 5, age: 18, - gender: 'female' + gender: 'female', }); o.set({ cool: true, gender: 'male' }); o.increment('count'); @@ -1269,60 +1288,61 @@ describe('ParseObject', () => { objectId: 'throwforarray', count: 5, age: 18, - gender: 'female' + gender: 'female', }); o.set({ cool: true, gender: 'male' }); - const err = "Parse.Object#revert expects either no, or a list of string, arguments."; + const err = 'Parse.Object#revert expects either no, or a list of string, arguments.'; - expect(function() { - o.revert(['age']) + expect(function () { + o.revert(['age']); }).toThrow(err); - expect(function() { - o.revert([]) + expect(function () { + o.revert([]); }).toThrow(err); - expect(function() { - o.revert('gender', ['age']) + expect(function () { + o.revert('gender', ['age']); }).toThrow(err); }); it('can fetchWithInclude', async () => { const objectController = CoreManager.getObjectController(); - const spy = jest.spyOn( - objectController, - 'fetch' - ) + const spy = jest + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); const parent = new ParseObject('Person'); - await parent.fetchWithInclude('child', { useMasterKey: true, sessionToken: '123'}); + await parent.fetchWithInclude('child', { + useMasterKey: true, + sessionToken: '123', + }); await parent.fetchWithInclude(['child']); await parent.fetchWithInclude([['child']]); expect(objectController.fetch).toHaveBeenCalledTimes(3); expect(objectController.fetch.mock.calls[0]).toEqual([ - parent, true, { useMasterKey: true, sessionToken: '123', include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[1]).toEqual([ - parent, true, { include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[2]).toEqual([ - parent, true, { include: ['child'] } + parent, + true, + { useMasterKey: true, sessionToken: '123', include: ['child'] }, ]); + expect(objectController.fetch.mock.calls[1]).toEqual([parent, true, { include: ['child'] }]); + expect(objectController.fetch.mock.calls[2]).toEqual([parent, true, { include: ['child'] }]); spy.mockRestore(); }); it('fetchAll with empty values', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); @@ -1334,10 +1354,12 @@ describe('ParseObject', () => { it('fetchAll with null', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); @@ -1405,58 +1427,56 @@ describe('ParseObject', () => { it('can fetchAllWithInclude', async () => { const objectController = CoreManager.getObjectController(); - const spy = jest.spyOn( - objectController, - 'fetch' - ) + const spy = jest + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); const parent = new ParseObject('Person'); - await ParseObject.fetchAllWithInclude([parent], 'child', { useMasterKey: true, sessionToken: '123'}); + await ParseObject.fetchAllWithInclude([parent], 'child', { + useMasterKey: true, + sessionToken: '123', + }); await ParseObject.fetchAllWithInclude([parent], ['child']); await ParseObject.fetchAllWithInclude([parent], [['child']]); expect(objectController.fetch).toHaveBeenCalledTimes(3); expect(objectController.fetch.mock.calls[0]).toEqual([ - [parent], true, { useMasterKey: true, sessionToken: '123', include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[1]).toEqual([ - [parent], true, { include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[2]).toEqual([ - [parent], true, { include: ['child'] } + [parent], + true, + { useMasterKey: true, sessionToken: '123', include: ['child'] }, ]); + expect(objectController.fetch.mock.calls[1]).toEqual([[parent], true, { include: ['child'] }]); + expect(objectController.fetch.mock.calls[2]).toEqual([[parent], true, { include: ['child'] }]); spy.mockRestore(); }); it('can fetchAllIfNeededWithInclude', async () => { const objectController = CoreManager.getObjectController(); - const spy = jest.spyOn( - objectController, - 'fetch' - ) + const spy = jest + .spyOn(objectController, 'fetch') .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}) .mockImplementationOnce(() => {}); const parent = new ParseObject('Person'); - await ParseObject.fetchAllIfNeededWithInclude([parent], 'child', { useMasterKey: true, sessionToken: '123'}); + await ParseObject.fetchAllIfNeededWithInclude([parent], 'child', { + useMasterKey: true, + sessionToken: '123', + }); await ParseObject.fetchAllIfNeededWithInclude([parent], ['child']); await ParseObject.fetchAllIfNeededWithInclude([parent], [['child']]); expect(objectController.fetch).toHaveBeenCalledTimes(3); expect(objectController.fetch.mock.calls[0]).toEqual([ - [parent], false, { useMasterKey: true, sessionToken: '123', include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[1]).toEqual([ - [parent], false, { include: ['child'] } - ]); - expect(objectController.fetch.mock.calls[2]).toEqual([ - [parent], false, { include: ['child'] } + [parent], + false, + { useMasterKey: true, sessionToken: '123', include: ['child'] }, ]); + expect(objectController.fetch.mock.calls[1]).toEqual([[parent], false, { include: ['child'] }]); + expect(objectController.fetch.mock.calls[2]).toEqual([[parent], false, { include: ['child'] }]); spy.mockRestore(); }); @@ -1464,7 +1484,7 @@ describe('ParseObject', () => { it('can check if object exists', async () => { const parent = new ParseObject('Person'); expect(await parent.exists()).toBe(false); - parent.id = '1234' + parent.id = '1234'; expect(await parent.exists()).toBe(true); jest.spyOn(mockQuery.prototype, 'get').mockImplementationOnce(() => { @@ -1488,20 +1508,22 @@ describe('ParseObject', () => { } }); - it('can save the object', (done) => { + it('can save the object', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - objectId: 'P5', - count: 1 - } - }]) + mockXHR([ + { + status: 200, + response: { + objectId: 'P5', + count: 1, + }, + }, + ]) ); const p = new ParseObject('Person'); p.set('age', 38); p.increment('count'); - p.save().then((obj) => { + p.save().then(obj => { expect(obj).toBe(p); expect(obj.get('age')).toBe(38); expect(obj.get('count')).toBe(1); @@ -1511,68 +1533,81 @@ describe('ParseObject', () => { }); }); - it('can save the object with key / value', (done) => { + it('can save the object with key / value', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - objectId: 'P8', - } - }]) + mockXHR([ + { + status: 200, + response: { + objectId: 'P8', + }, + }, + ]) ); const p = new ParseObject('Person'); - p.save('foo', 'bar').then((obj) => { + p.save('foo', 'bar').then(obj => { expect(obj).toBe(p); expect(obj.get('foo')).toBe('bar'); done(); }); }); - it('accepts attribute changes on save', (done) => { + it('accepts attribute changes on save', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { objectId: 'newattributes' } - }]) + mockXHR([ + { + status: 200, + response: { objectId: 'newattributes' }, + }, + ]) ); let o = new ParseObject('Item'); - o.save({ key: 'value' }).then(() => { - expect(o.get('key')).toBe('value'); + o.save({ key: 'value' }) + .then(() => { + expect(o.get('key')).toBe('value'); - o = new ParseObject('Item'); - return o.save({ ACL: 'not an acl' }); - }).then(null, (error) => { - expect(error.code).toBe(-1); - done(); - }); + o = new ParseObject('Item'); + return o.save({ ACL: 'not an acl' }); + }) + .then(null, error => { + expect(error.code).toBe(-1); + done(); + }); }); it('accepts context on save', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { objectId: 'newattributes' } - }]) + mockXHR([ + { + status: 200, + response: { objectId: 'newattributes' }, + }, + ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); // Save object - const context = {a: "a"}; + const context = { a: 'a' }; const obj = new ParseObject('Item'); - await obj.save(null, {context}); + await obj.save(null, { context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); }); - it('interpolates delete operations', (done) => { + it('interpolates delete operations', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { objectId: 'newattributes', deletedKey: {__op: 'Delete'} } - }]) + mockXHR([ + { + status: 200, + response: { + objectId: 'newattributes', + deletedKey: { __op: 'Delete' }, + }, + }, + ]) ); const o = new ParseObject('Item'); o.save({ key: 'value', deletedKey: 'keyToDelete' }).then(() => { @@ -1586,9 +1621,11 @@ describe('ParseObject', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const p = new ParseObject('Person'); p.set('age', 38); const result = p.save().then(() => { @@ -1611,11 +1648,11 @@ describe('ParseObject', () => { it('will queue save operations', async () => { const xhrs = []; - RESTController._setXHR(function() { + RESTController._setXHR(function () { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; xhrs.push(xhr); return xhr; @@ -1653,13 +1690,15 @@ describe('ParseObject', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const p = new ParseObject('Per$on'); expect(p._getPendingOps().length).toBe(1); p.increment('updates'); - const result = p.save().then(null, (err) => { + const result = p.save().then(null, err => { expect(err.code).toBe(103); expect(err.message).toBe('Invalid class name'); expect(p._getPendingOps().length).toBe(1); @@ -1670,7 +1709,10 @@ describe('ParseObject', () => { await flushPromises(); xhr.status = 404; - xhr.responseText = JSON.stringify({ code: 103, error: 'Invalid class name' }); + xhr.responseText = JSON.stringify({ + code: 103, + error: 'Invalid class name', + }); xhr.readyState = 4; xhr.onreadystatechange(); await result; @@ -1678,11 +1720,11 @@ describe('ParseObject', () => { it('will merge pending Ops when a save fails and others are pending', async () => { const xhrs = []; - RESTController._setXHR(function() { + RESTController._setXHR(function () { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; xhrs.push(xhr); return xhr; @@ -1702,26 +1744,29 @@ describe('ParseObject', () => { expect(p._getPendingOps().length).toBe(3); xhrs[0].status = 404; - xhrs[0].responseText = JSON.stringify({ code: 103, error: 'Invalid class name' }); + xhrs[0].responseText = JSON.stringify({ + code: 103, + error: 'Invalid class name', + }); xhrs[0].readyState = 4; xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); expect(p._getPendingOps().length).toBe(2); expect(p._getPendingOps()[0]).toEqual({ - updates: new ParseOp.SetOp(12) + updates: new ParseOp.SetOp(12), }); }); it('will deep-save the children of an object', async () => { const xhrs = []; - RESTController._setXHR(function() { + RESTController._setXHR(function () { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; xhrs.push(xhr); return xhr; @@ -1739,10 +1784,8 @@ describe('ParseObject', () => { await flushPromises(); expect(xhrs.length).toBe(1); - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - xhrs[0].responseText = JSON.stringify([ { success: { objectId: 'child' } } ]); + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'child' } }]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); @@ -1759,9 +1802,7 @@ describe('ParseObject', () => { const child = new ParseObject('Item'); parent.set('child', child); child.set('parent', parent); - expect(parent.save.bind(parent)).toThrow( - 'Cannot create a pointer to an unsaved Object.' - ); + expect(parent.save.bind(parent)).toThrow('Cannot create a pointer to an unsaved Object.'); }); it('will fail for deeper unsaved objects', () => { @@ -1771,9 +1812,7 @@ describe('ParseObject', () => { parent.set('child', child); child.set('child', grandchild); - expect(parent.save.bind(parent)).toThrow( - 'Cannot create a pointer to an unsaved Object.' - ); + expect(parent.save.bind(parent)).toThrow('Cannot create a pointer to an unsaved Object.'); }); it('does not mark shallow objects as dirty', () => { @@ -1788,16 +1827,18 @@ describe('ParseObject', () => { it('can fetch an object given an id', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - count: 10 - } - }]) + mockXHR([ + { + status: 200, + response: { + count: 10, + }, + }, + ]) ); const p = new ParseObject('Person'); p.id = 'P55'; - await p.fetch().then((res) => { + await p.fetch().then(res => { expect(p).toBe(res); expect(p.attributes).toEqual({ count: 10 }); }); @@ -1806,21 +1847,20 @@ describe('ParseObject', () => { it('throw for fetch with empty string as ID', async () => { expect.assertions(1); CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - count: 10 - } - }]) + mockXHR([ + { + status: 200, + response: { + count: 10, + }, + }, + ]) ); const p = new ParseObject('Person'); p.id = ''; - await expect(p.fetch()) - .rejects - .toThrowError(new ParseError( - ParseError.MISSING_OBJECT_ID, - 'Object does not have an ID' - )); + await expect(p.fetch()).rejects.toThrowError( + new ParseError(ParseError.MISSING_OBJECT_ID, 'Object does not have an ID') + ); }); it('should fail saveAll batch cycle', async () => { @@ -1834,28 +1874,30 @@ describe('ParseObject', () => { } }); - it('should fail on invalid date', (done) => { + it('should fail on invalid date', done => { const obj = new ParseObject('Item'); obj.set('when', new Date(Date.parse(null))); - ParseObject.saveAll([obj]).then(() => { - done.fail('Expected invalid date to fail'); - }).catch((error) => { - expect(error[0].code).toEqual(ParseError.INCORRECT_TYPE); - expect(error[0].message).toEqual('Tried to encode an invalid date.'); - done(); - }); + ParseObject.saveAll([obj]) + .then(() => { + done.fail('Expected invalid date to fail'); + }) + .catch(error => { + expect(error[0].code).toEqual(ParseError.INCORRECT_TYPE); + expect(error[0].message).toEqual('Tried to encode an invalid date.'); + done(); + }); jest.runAllTicks(); }); it('can save a ring of objects, given one exists', async () => { const xhrs = []; - RESTController._setXHR(function() { + RESTController._setXHR(function () { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; xhrs.push(xhr); return xhr; @@ -1874,23 +1916,21 @@ describe('ParseObject', () => { await flushPromises(); expect(xhrs.length).toBe(1); - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual( - [{ + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ + { method: 'POST', path: '/1/classes/Item', body: { child: { __type: 'Pointer', className: 'Item', - objectId: 'child' - } - } - }] - ); - xhrs[0].responseText = JSON.stringify([ { success: { objectId: 'parent' } } ]); + objectId: 'child', + }, + }, + }, + ]); + xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'parent' } }]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); @@ -1898,7 +1938,7 @@ describe('ParseObject', () => { expect(parent.id).toBe('parent'); expect(xhrs.length).toBe(2); - xhrs[1].responseText = JSON.stringify([ { success: {} } ]); + xhrs[1].responseText = JSON.stringify([{ success: {} }]); xhrs[1].onreadystatechange(); jest.runAllTicks(); @@ -1908,20 +1948,22 @@ describe('ParseObject', () => { it('accepts context on saveAll', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); // Save object - const context = {a: "saveAll"}; + const context = { a: 'saveAll' }; const obj = new ParseObject('Item'); obj.id = 'pid'; obj.set('test', 'value'); - await ParseObject.saveAll([obj], { context, useMasterKey: true }) + await ParseObject.saveAll([obj], { context, useMasterKey: true }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); @@ -1930,19 +1972,21 @@ describe('ParseObject', () => { it('accepts context on destroyAll', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); // Save object - const context = {a: "b"}; + const context = { a: 'b' }; const obj = new ParseObject('Item'); obj.id = 'pid'; - await ParseObject.destroyAll([obj], { context: context }) + await ParseObject.destroyAll([obj], { context: context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); @@ -1951,10 +1995,12 @@ describe('ParseObject', () => { it('destroyAll with options', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); @@ -1968,16 +2014,18 @@ describe('ParseObject', () => { }); const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); - expect(jsonBody._MasterKey).toBe('C') + expect(jsonBody._MasterKey).toBe('C'); expect(jsonBody._SessionToken).toBe('r:1234'); }); it('destroyAll with empty values', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); @@ -1992,15 +2040,17 @@ describe('ParseObject', () => { it('destroyAll unsaved objects', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{}] - }]) + mockXHR([ + { + status: 200, + response: [{}], + }, + ]) ); const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); - const obj = new ParseObject('Item') + const obj = new ParseObject('Item'); const results = await ParseObject.destroyAll([obj]); expect(results).toEqual([obj]); expect(controller.ajax).toHaveBeenCalledTimes(0); @@ -2008,18 +2058,22 @@ describe('ParseObject', () => { it('destroyAll handle error response', async () => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: [{ - error: { - code: 101, - error: 'Object not found', - } - }] - }]) + mockXHR([ + { + status: 200, + response: [ + { + error: { + code: 101, + error: 'Object not found', + }, + }, + ], + }, + ]) ); - const obj = new ParseObject('Item') + const obj = new ParseObject('Item'); obj.id = 'toDelete1'; try { await ParseObject.destroyAll([obj]); @@ -2031,13 +2085,13 @@ describe('ParseObject', () => { it('can save a chain of unsaved objects', async () => { const xhrs = []; - RESTController._setXHR(function() { + RESTController._setXHR(function () { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; xhrs.push(xhr); return xhr; @@ -2059,108 +2113,109 @@ describe('ParseObject', () => { await flushPromises(); expect(xhrs.length).toBe(1); - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual( - [{ + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ + { method: 'POST', path: '/1/classes/Item', - body: {} - }] - ); - xhrs[0].responseText = JSON.stringify([ { success: { objectId: 'grandchild' } } ]); + body: {}, + }, + ]); + xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'grandchild' } }]); xhrs[0].onreadystatechange(); jest.runAllTicks(); await flushPromises(); expect(xhrs.length).toBe(2); - expect(xhrs[1].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests).toEqual( - [{ + expect(xhrs[1].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests).toEqual([ + { method: 'POST', path: '/1/classes/Item', body: { child: { __type: 'Pointer', className: 'Item', - objectId: 'grandchild' - } - } - }] - ); - xhrs[1].responseText = JSON.stringify([ { success: { objectId: 'child' } } ]); + objectId: 'grandchild', + }, + }, + }, + ]); + xhrs[1].responseText = JSON.stringify([{ success: { objectId: 'child' } }]); xhrs[1].onreadystatechange(); jest.runAllTicks(); await flushPromises(); expect(xhrs.length).toBe(3); - expect(xhrs[2].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests).toEqual( - [{ + expect(xhrs[2].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests).toEqual([ + { method: 'POST', path: '/1/classes/Item', body: { child: { __type: 'Pointer', className: 'Item', - objectId: 'child' - } - } - }] - ); - xhrs[2].responseText = JSON.stringify([ { success: { objectId: 'parent' } } ]); + objectId: 'child', + }, + }, + }, + ]); + xhrs[2].responseText = JSON.stringify([{ success: { objectId: 'parent' } }]); xhrs[2].onreadystatechange(); jest.runAllTicks(); await result; }); - it('can update fields via a fetch() call', (done) => { + it('can update fields via a fetch() call', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - count: 11 - } - }, { - status: 200, - response: { - count: 20 - } - }]) + mockXHR([ + { + status: 200, + response: { + count: 11, + }, + }, + { + status: 200, + response: { + count: 20, + }, + }, + ]) ); const p = new ParseObject('Person'); p.id = 'P55'; p.increment('count'); - p.save().then(() => { - expect(p.get('count')).toBe(11); - return p.fetch(); - }).then(() => { - expect(p.get('count')).toBe(20); - expect(p.dirty()).toBe(false); - done(); - }); + p.save() + .then(() => { + expect(p.get('count')).toBe(11); + return p.fetch(); + }) + .then(() => { + expect(p.get('count')).toBe(20); + expect(p.dirty()).toBe(false); + done(); + }); }); - it('replaces old data when fetch() is called', (done) => { + it('replaces old data when fetch() is called', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - count: 10 - } - }]) + mockXHR([ + { + status: 200, + response: { + count: 10, + }, + }, + ]) ); const p = ParseObject.fromJSON({ className: 'Person', objectId: 'P200', name: 'Fred', - count: 0 + count: 0, }); expect(p.get('name')).toBe('Fred'); expect(p.get('count')).toBe(0); @@ -2176,15 +2231,19 @@ describe('ParseObject', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const p = new ParseObject('Person'); p.id = 'pid'; const result = p.destroy().then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid', true] - ); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid', + true, + ]); expect(JSON.parse(xhr.send.mock.calls[0])._method).toBe('DELETE'); }); jest.runAllTicks(); @@ -2200,19 +2259,21 @@ describe('ParseObject', () => { it('accepts context on destroy', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: {} - }]) + mockXHR([ + { + status: 200, + response: {}, + }, + ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); jest.spyOn(controller, 'ajax'); // Save object - const context = {a: "a"}; + const context = { a: 'a' }; const obj = new ParseObject('Item'); obj.id = 'pid'; - await obj.destroy({context}); + await obj.destroy({ context }); // Validate const jsonBody = JSON.parse(controller.ajax.mock.calls[0][2]); expect(jsonBody._context).toEqual(context); @@ -2229,25 +2290,25 @@ describe('ParseObject', () => { expect(controller.ajax).toHaveBeenCalledTimes(0); }); - it('can save an array of objects', async (done) => { + it('can save an array of objects', async done => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); } ParseObject.saveAll(objects).then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); + expect(xhr.open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); expect(JSON.parse(xhr.send.mock.calls[0]).requests[0]).toEqual({ method: 'POST', path: '/1/classes/Person', - body: {} + body: {}, }); done(); }); @@ -2266,7 +2327,7 @@ describe('ParseObject', () => { jest.runAllTicks(); }); - it('can saveAll with batchSize', async (done) => { + it('can saveAll with batchSize', async done => { const xhrs = []; for (let i = 0; i < 2; i++) { xhrs[i] = { @@ -2274,22 +2335,20 @@ describe('ParseObject', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); const objects = []; for (let i = 0; i < 22; i++) { objects[i] = new ParseObject('Person'); } ParseObject.saveAll(objects, { batchSize: 20 }).then(() => { - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(xhrs[1].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(xhrs[1].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); done(); }); jest.runAllTicks(); @@ -2329,7 +2388,7 @@ describe('ParseObject', () => { jest.runAllTicks(); }); - it('can saveAll with global batchSize', async (done) => { + it('can saveAll with global batchSize', async done => { const xhrs = []; for (let i = 0; i < 2; i++) { xhrs[i] = { @@ -2337,22 +2396,20 @@ describe('ParseObject', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); const objects = []; for (let i = 0; i < 22; i++) { objects[i] = new ParseObject('Person'); } ParseObject.saveAll(objects).then(() => { - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(xhrs[1].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(xhrs[1].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); done(); }); jest.runAllTicks(); @@ -2392,7 +2449,7 @@ describe('ParseObject', () => { jest.runAllTicks(); }); - it('returns the first error when saving an array of objects', async (done) => { + it('returns the first error when saving an array of objects', async done => { const xhrs = []; for (let i = 0; i < 2; i++) { xhrs[i] = { @@ -2400,16 +2457,18 @@ describe('ParseObject', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); const objects = []; for (let i = 0; i < 22; i++) { objects[i] = new ParseObject('Person'); } - ParseObject.saveAll(objects).then(null, (error) => { + ParseObject.saveAll(objects).then(null, error => { // The second batch never ran expect(xhrs[1].open.mock.calls.length).toBe(0); expect(objects[19].dirty()).toBe(false); @@ -2452,20 +2511,24 @@ describe('ObjectController', () => { jest.clearAllMocks(); }); - it('can fetch a single object', async (done) => { + it('can fetch a single object', async done => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const o = new ParseObject('Person'); o.id = 'pid'; objectController.fetch(o).then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid', true] - ); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid', + true, + ]); const body = JSON.parse(xhr.send.mock.calls[0]); expect(body._method).toBe('GET'); done(); @@ -2482,10 +2545,12 @@ describe('ObjectController', () => { it('accepts context on fetch', async () => { // Mock XHR CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: {} - }]) + mockXHR([ + { + status: 200, + response: {}, + }, + ]) ); // Spy on REST controller const controller = CoreManager.getRESTController(); @@ -2500,14 +2565,14 @@ describe('ObjectController', () => { expect(jsonBody._context).toEqual(context); }); - it('can fetch an array of objects', (done) => { + it('can fetch an array of objects', done => { const objectController = CoreManager.getObjectController(); const objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); objects[i].id = 'pid' + i; } - objectController.fetch(objects).then((results) => { + objectController.fetch(objects).then(results => { expect(results.length).toBe(5); expect(results[0] instanceof ParseObject).toBe(true); expect(results[0].id).toBe('pid0'); @@ -2516,20 +2581,24 @@ describe('ObjectController', () => { }); }); - it('can fetch a single object with include', async (done) => { + it('can fetch a single object with include', async done => { const objectController = CoreManager.getObjectController(); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const o = new ParseObject('Person'); o.id = 'pid'; objectController.fetch(o, false, { include: ['child'] }).then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid', true] - ); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid', + true, + ]); const body = JSON.parse(xhr.send.mock.calls[0]); expect(body._method).toBe('GET'); done(); @@ -2550,7 +2619,9 @@ describe('ObjectController', () => { objects[i] = new ParseObject('Person'); objects[i].id = 'pid' + i; } - const results = await objectController.fetch(objects, false, { include: ['child'] }); + const results = await objectController.fetch(objects, false, { + include: ['child'], + }); expect(results.length).toBe(5); expect(results[0] instanceof ParseObject).toBe(true); expect(results[0].id).toBe('pid0'); @@ -2562,34 +2633,43 @@ describe('ObjectController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const p = new ParseObject('Person'); p.id = 'pid'; - const result = objectController.destroy(p, {}).then(async () => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid', true] - ); - expect(JSON.parse(xhr.send.mock.calls[0])._method).toBe('DELETE'); - const p2 = new ParseObject('Person'); - p2.id = 'pid2'; - const destroy = objectController.destroy(p2, { - useMasterKey: true + const result = objectController + .destroy(p, {}) + .then(async () => { + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid', + true, + ]); + expect(JSON.parse(xhr.send.mock.calls[0])._method).toBe('DELETE'); + const p2 = new ParseObject('Person'); + p2.id = 'pid2'; + const destroy = objectController.destroy(p2, { + useMasterKey: true, + }); + jest.runAllTicks(); + await flushPromises(); + xhr.onreadystatechange(); + jest.runAllTicks(); + return destroy; + }) + .then(() => { + expect(xhr.open.mock.calls[1]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid2', + true, + ]); + const body = JSON.parse(xhr.send.mock.calls[1]); + expect(body._method).toBe('DELETE'); + expect(body._MasterKey).toBe('C'); }); - jest.runAllTicks(); - await flushPromises(); - xhr.onreadystatechange(); - jest.runAllTicks(); - return destroy; - }).then(() => { - expect(xhr.open.mock.calls[1]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid2', true] - ); - const body = JSON.parse(xhr.send.mock.calls[1]); - expect(body._method).toBe('DELETE'); - expect(body._MasterKey).toBe('C'); - }); jest.runAllTicks(); await flushPromises(); xhr.status = 200; @@ -2607,66 +2687,73 @@ describe('ObjectController', () => { xhrs[i] = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; xhrs[i].status = 200; xhrs[i].responseText = JSON.stringify({}); xhrs[i].readyState = 4; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); let objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); objects[i].id = 'pid' + i; } - const result = objectController.destroy(objects, { batchSize: 20}).then(async () => { - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ - { - method: 'DELETE', - path: '/1/classes/Person/pid0', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid1', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid2', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid3', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid4', - body: {} + const result = objectController + .destroy(objects, { batchSize: 20 }) + .then(async () => { + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ + { + method: 'DELETE', + path: '/1/classes/Person/pid0', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid1', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid2', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid3', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid4', + body: {}, + }, + ]); + + objects = []; + for (let i = 0; i < 22; i++) { + objects[i] = new ParseObject('Person'); + objects[i].id = 'pid' + i; } - ]); - - objects = []; - for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject('Person'); - objects[i].id = 'pid' + i; - } - const destroy = objectController.destroy(objects, { batchSize: 20 }); - jest.runAllTicks(); - await flushPromises(); - xhrs[1].onreadystatechange(); - jest.runAllTicks(); - await flushPromises(); - expect(xhrs[1].open.mock.calls.length).toBe(1); - xhrs[2].onreadystatechange(); - jest.runAllTicks(); - return destroy; - }).then(() => { - expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests.length).toBe(20); - expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests.length).toBe(2); - }); + const destroy = objectController.destroy(objects, { batchSize: 20 }); + jest.runAllTicks(); + await flushPromises(); + xhrs[1].onreadystatechange(); + jest.runAllTicks(); + await flushPromises(); + expect(xhrs[1].open.mock.calls.length).toBe(1); + xhrs[2].onreadystatechange(); + jest.runAllTicks(); + return destroy; + }) + .then(() => { + expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests.length).toBe(20); + expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests.length).toBe(2); + }); jest.runAllTicks(); await flushPromises(); @@ -2682,66 +2769,73 @@ describe('ObjectController', () => { xhrs[i] = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; xhrs[i].status = 200; xhrs[i].responseText = JSON.stringify({}); xhrs[i].readyState = 4; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); let objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); objects[i].id = 'pid' + i; } - const result = objectController.destroy(objects, {}).then(async () => { - expect(xhrs[0].open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); - expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ - { - method: 'DELETE', - path: '/1/classes/Person/pid0', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid1', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid2', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid3', - body: {} - }, { - method: 'DELETE', - path: '/1/classes/Person/pid4', - body: {} + const result = objectController + .destroy(objects, {}) + .then(async () => { + expect(xhrs[0].open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); + expect(JSON.parse(xhrs[0].send.mock.calls[0]).requests).toEqual([ + { + method: 'DELETE', + path: '/1/classes/Person/pid0', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid1', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid2', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid3', + body: {}, + }, + { + method: 'DELETE', + path: '/1/classes/Person/pid4', + body: {}, + }, + ]); + + objects = []; + for (let i = 0; i < 22; i++) { + objects[i] = new ParseObject('Person'); + objects[i].id = 'pid' + i; } - ]); - - objects = []; - for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject('Person'); - objects[i].id = 'pid' + i; - } - const destroy = objectController.destroy(objects, {}); - jest.runAllTicks(); - await flushPromises(); - xhrs[1].onreadystatechange(); - jest.runAllTicks(); - await flushPromises(); - expect(xhrs[1].open.mock.calls.length).toBe(1); - xhrs[2].onreadystatechange(); - jest.runAllTicks(); - return destroy; - }).then(() => { - expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests.length).toBe(20); - expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests.length).toBe(2); - }); + const destroy = objectController.destroy(objects, {}); + jest.runAllTicks(); + await flushPromises(); + xhrs[1].onreadystatechange(); + jest.runAllTicks(); + await flushPromises(); + expect(xhrs[1].open.mock.calls.length).toBe(1); + xhrs[2].onreadystatechange(); + jest.runAllTicks(); + return destroy; + }) + .then(() => { + expect(JSON.parse(xhrs[1].send.mock.calls[0]).requests.length).toBe(20); + expect(JSON.parse(xhrs[2].send.mock.calls[0]).requests.length).toBe(2); + }); jest.runAllTicks(); await flushPromises(); @@ -2755,16 +2849,20 @@ describe('ObjectController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const p = new ParseObject('Person'); p.id = 'pid'; p.set('key', 'value'); const result = objectController.save(p, {}).then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/Person/pid', true] - ); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/Person/pid', + true, + ]); const body = JSON.parse(xhr.send.mock.calls[0]); expect(body.key).toBe('value'); }); @@ -2778,7 +2876,7 @@ describe('ObjectController', () => { await result; }); - it('returns an empty promise from an empty save', (done) => { + it('returns an empty promise from an empty save', done => { const objectController = CoreManager.getObjectController(); objectController.save().then(() => { done(); @@ -2795,26 +2893,22 @@ describe('ObjectController', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); const files = [ new ParseFile('parse.txt', { base64: 'ParseA==' }), new ParseFile('parse2.txt', { base64: 'ParseA==' }), - new ParseFile('parse3.txt', { base64: 'ParseA==' }) + new ParseFile('parse3.txt', { base64: 'ParseA==' }), ]; const result = objectController.save(files, {}).then(() => { - expect(files[0].url()).toBe( - 'http://files.parsetfss.com/a/parse.txt' - ); - expect(files[1].url()).toBe( - 'http://files.parsetfss.com/a/parse2.txt' - ); - expect(files[2].url()).toBe( - 'http://files.parsetfss.com/a/parse3.txt' - ); + expect(files[0].url()).toBe('http://files.parsetfss.com/a/parse.txt'); + expect(files[1].url()).toBe('http://files.parsetfss.com/a/parse2.txt'); + expect(files[2].url()).toBe('http://files.parsetfss.com/a/parse3.txt'); }); jest.runAllTicks(); await flushPromises(); @@ -2822,7 +2916,7 @@ describe('ObjectController', () => { for (let i = 0; i < 3; i++) { xhrs[i].responseText = JSON.stringify({ name: 'parse.txt', - url: 'http://files.parsetfss.com/a/' + names[i] + url: 'http://files.parsetfss.com/a/' + names[i], }); await flushPromises(); xhrs[i].onreadystatechange(); @@ -2840,61 +2934,69 @@ describe('ObjectController', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); const objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); } - const result = objectController.save(objects, {}).then(async (results) => { - expect(results.length).toBe(5); - expect(results[0].id).toBe('pid0'); - expect(results[0].get('index')).toBe(0); - expect(results[0].dirty()).toBe(false); - - const response = []; - for (let i = 0; i < 22; i++) { - objects[i] = new ParseObject('Person'); - objects[i].set('index', i); - response.push({ - success: { objectId: 'pid' + i } - }); - } - const save = objectController.save(objects, {}); - jest.runAllTicks(); - await flushPromises(); - - xhrs[1].responseText = JSON.stringify(response.slice(0, 20)); - xhrs[2].responseText = JSON.stringify(response.slice(20)); - - // Objects in the second batch will not be prepared for save yet - // This means they can also be modified before the first batch returns - expect( - SingleInstanceStateController.getState({ className: 'Person', id: objects[20]._getId() }).pendingOps.length - ).toBe(1); - objects[20].set('index', 0); - - xhrs[1].onreadystatechange(); - jest.runAllTicks(); - await flushPromises(); - expect(objects[0].dirty()).toBe(false); - expect(objects[0].id).toBe('pid0'); - expect(objects[20].dirty()).toBe(true); - expect(objects[20].id).toBe(undefined); - - xhrs[2].onreadystatechange(); - jest.runAllTicks(); - await flushPromises(); - expect(objects[20].dirty()).toBe(false); - expect(objects[20].get('index')).toBe(0); - expect(objects[20].id).toBe('pid20'); - return save; - }).then((results) => { - expect(results.length).toBe(22); - }); + const result = objectController + .save(objects, {}) + .then(async results => { + expect(results.length).toBe(5); + expect(results[0].id).toBe('pid0'); + expect(results[0].get('index')).toBe(0); + expect(results[0].dirty()).toBe(false); + + const response = []; + for (let i = 0; i < 22; i++) { + objects[i] = new ParseObject('Person'); + objects[i].set('index', i); + response.push({ + success: { objectId: 'pid' + i }, + }); + } + const save = objectController.save(objects, {}); + jest.runAllTicks(); + await flushPromises(); + + xhrs[1].responseText = JSON.stringify(response.slice(0, 20)); + xhrs[2].responseText = JSON.stringify(response.slice(20)); + + // Objects in the second batch will not be prepared for save yet + // This means they can also be modified before the first batch returns + expect( + SingleInstanceStateController.getState({ + className: 'Person', + id: objects[20]._getId(), + }).pendingOps.length + ).toBe(1); + objects[20].set('index', 0); + + xhrs[1].onreadystatechange(); + jest.runAllTicks(); + await flushPromises(); + expect(objects[0].dirty()).toBe(false); + expect(objects[0].id).toBe('pid0'); + expect(objects[20].dirty()).toBe(true); + expect(objects[20].id).toBe(undefined); + + xhrs[2].onreadystatechange(); + jest.runAllTicks(); + await flushPromises(); + expect(objects[20].dirty()).toBe(false); + expect(objects[20].get('index')).toBe(0); + expect(objects[20].id).toBe('pid20'); + return save; + }) + .then(results => { + expect(results.length).toBe(22); + }); jest.runAllTicks(); await flushPromises(); xhrs[0].responseText = JSON.stringify([ @@ -2917,23 +3019,27 @@ describe('ObjectController', () => { open: jest.fn(), send: jest.fn(), status: 200, - readyState: 4 + readyState: 4, }; } let current = 0; - RESTController._setXHR(function() { return xhrs[current++]; }); + RESTController._setXHR(function () { + return xhrs[current++]; + }); xhrs[0].responseText = JSON.stringify([{ success: { objectId: 'i333' } }]); xhrs[1].responseText = JSON.stringify({}); const brand = ParseObject.fromJSON({ className: 'Brand', objectId: 'b123', - items: [{ __type: 'Pointer', objectId: 'i222', className: 'Item' }] + items: [{ __type: 'Pointer', objectId: 'i222', className: 'Item' }], }); expect(brand._getSaveJSON()).toEqual({}); const items = brand.get('items'); items.push(new ParseObject('Item')); brand.set('items', items); - expect(function() { brand.save(); }).not.toThrow(); + expect(function () { + brand.save(); + }).not.toThrow(); jest.runAllTicks(); await flushPromises(); xhrs[0].onreadystatechange(); @@ -2968,7 +3074,7 @@ describe('ParseObject (unique instance mode)', () => { it('can be created with initial attributes', () => { const o = new ParseObject({ className: 'Item', - value: 12 + value: 12, }); expect(o.className).toBe('Item'); expect(o.attributes).toEqual({ value: 12 }); @@ -2979,7 +3085,7 @@ describe('ParseObject (unique instance mode)', () => { className: 'Item', createdAt: '2013-12-14T04:51:19Z', objectId: 'I1', - size: 'medium' + size: 'medium', }; const o = ParseObject.fromJSON(json); expect(o.className).toBe('Item'); @@ -2987,7 +3093,7 @@ describe('ParseObject (unique instance mode)', () => { expect(o.attributes).toEqual({ size: 'medium', createdAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), - updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)) + updatedAt: new Date(Date.UTC(2013, 11, 14, 4, 51, 19)), }); expect(o.dirty()).toBe(false); }); @@ -2996,23 +3102,23 @@ describe('ParseObject (unique instance mode)', () => { let o = new ParseObject('Item'); o.set({ size: 'large', - inStock: 18 + inStock: 18, }); expect(o.toJSON()).toEqual({ size: 'large', - inStock: 18 + inStock: 18, }); o = new ParseObject('Item'); o._finishFetch({ objectId: 'O2', size: 'medium', - inStock: 12 + inStock: 12, }); expect(o.id).toBe('O2'); expect(o.toJSON()).toEqual({ objectId: 'O2', size: 'medium', - inStock: 12 + inStock: 12, }); }); @@ -3021,7 +3127,7 @@ describe('ParseObject (unique instance mode)', () => { className: 'Item', objectId: 'anObjectId', value: 12, - valid: true + valid: true, }); o.set({ value: 14 }); expect(o.get('value')).toBe(14); @@ -3036,7 +3142,7 @@ describe('ParseObject (unique instance mode)', () => { const o2 = ParseObject.fromJSON({ className: 'Item', - tags: ['#tbt'] + tags: ['#tbt'], }); o2.add('tags', '#nofilter'); @@ -3051,20 +3157,22 @@ describe('ParseObject (unique instance mode)', () => { expect(o2.get('tags')).toEqual([]); }); - it('can save the object', (done) => { + it('can save the object', done => { CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - objectId: 'P1', - count: 1 - } - }]) + mockXHR([ + { + status: 200, + response: { + objectId: 'P1', + count: 1, + }, + }, + ]) ); const p = new ParseObject('Person'); p.set('age', 38); p.increment('count'); - p.save().then((obj) => { + p.save().then(obj => { expect(obj).toBe(p); expect(obj.get('age')).toBe(38); expect(obj.get('count')).toBe(1); @@ -3078,21 +3186,21 @@ describe('ParseObject (unique instance mode)', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const objects = []; for (let i = 0; i < 5; i++) { objects[i] = new ParseObject('Person'); } const result = ParseObject.saveAll(objects).then(() => { - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/batch', true] - ); + expect(xhr.open.mock.calls[0]).toEqual(['POST', 'https://api.parse.com/1/batch', true]); expect(JSON.parse(xhr.send.mock.calls[0]).requests[0]).toEqual({ method: 'POST', path: '/1/classes/Person', - body: {} + body: {}, }); }); jest.runAllTicks(); @@ -3116,7 +3224,7 @@ describe('ParseObject (unique instance mode)', () => { const o = new ParseObject({ className: 'Item', objectId: 'anObjectId', - value: 12 + value: 12, }); o.id = 'otherId'; expect(o.get('value')).toBe(12); @@ -3126,12 +3234,12 @@ describe('ParseObject (unique instance mode)', () => { const o = new ParseObject({ className: 'Item', objectId: 'anObjectId', - value: 12 + value: 12, }); const o2 = new ParseObject({ className: 'Item', objectId: 'anObjectId', - value: 12 + value: 12, }); o.set({ value: 100 }); expect(o.get('value')).toBe(100); @@ -3187,7 +3295,7 @@ describe('ParseObject Subclasses', () => { expect(o.toPointer()).toEqual({ __type: 'Pointer', className: 'MyObject', - objectId: 'anObjectId' + objectId: 'anObjectId', }); expect(o.doSomething()).toBe(5); @@ -3198,7 +3306,7 @@ describe('ParseObject Subclasses', () => { expect(o2.toPointer()).toEqual({ __type: 'Pointer', className: 'MyObject', - objectId: 'otherId' + objectId: 'otherId', }); expect(o2.doSomething()).toBe(5); }); @@ -3206,15 +3314,9 @@ describe('ParseObject Subclasses', () => { it('respects readonly attributes of subclasses', () => { const o = new MyObject(); o.set('readwrite', true); - expect(o.set.bind(o, 'readonly')).toThrow( - 'Cannot modify readonly attribute: readonly' - ); - expect(o.set.bind(o, 'static')).toThrow( - 'Cannot modify readonly attribute: static' - ); - expect(o.set.bind(o, 'frozen')).toThrow( - 'Cannot modify readonly attribute: frozen' - ); + expect(o.set.bind(o, 'readonly')).toThrow('Cannot modify readonly attribute: readonly'); + expect(o.set.bind(o, 'static')).toThrow('Cannot modify readonly attribute: static'); + expect(o.set.bind(o, 'frozen')).toThrow('Cannot modify readonly attribute: frozen'); }); it('registerSubclass errors', () => { @@ -3228,13 +3330,15 @@ describe('ParseObject Subclasses', () => { expect(() => { ParseObject.registerSubclass('TestObject', {}); - }).toThrow('You must register the subclass constructor. Did you attempt to register an instance of the subclass?'); + }).toThrow( + 'You must register the subclass constructor. Did you attempt to register an instance of the subclass?' + ); }); it('can inflate subclasses from server JSON', () => { const json = { className: 'MyObject', - objectId: 'anotherId' + objectId: 'anotherId', }; const o = ParseObject.fromJSON(json); expect(o instanceof ParseObject).toBe(true); @@ -3247,14 +3351,14 @@ describe('ParseObject Subclasses', () => { const o = new MyObject(); o.set({ size: 'large', - count: 7 + count: 7, }); const o2 = o.clone(); expect(o2 instanceof MyObject).toBe(true); expect(o2.className).toBe('MyObject'); expect(o2.attributes).toEqual({ size: 'large', - count: 7 + count: 7, }); expect(o2.id).toBe(undefined); expect(o.equals(o2)).toBe(false); @@ -3268,11 +3372,15 @@ describe('ParseObject Subclasses', () => { }); jest.spyOn(o, 'set'); o.clear(); - expect(o.set).toHaveBeenCalledWith({ - count: true, size: true, - }, { - unset: true, - }); + expect(o.set).toHaveBeenCalledWith( + { + count: true, + size: true, + }, + { + unset: true, + } + ); }); }); @@ -3290,7 +3398,7 @@ describe('ParseObject extensions', () => { yo.set('greeting', 'yo'); expect(yo.get('greeting')).toBe('yo'); expect(yo.attributes).toEqual({ - greeting: 'yo' + greeting: 'yo', }); const yo2 = YourObject.createWithoutData('otherId'); @@ -3299,16 +3407,24 @@ describe('ParseObject extensions', () => { expect(yo2.toPointer()).toEqual({ __type: 'Pointer', className: 'YourObject', - objectId: 'otherId' + objectId: 'otherId', }); }); it('can extend the prototype and statics of ParseObject', () => { - const ExtendedObject = ParseObject.extend('ExtendedObject', { - getFoo() { return 12; } - }, { - isFoo(value) { return value === 'foo'; } - }); + const ExtendedObject = ParseObject.extend( + 'ExtendedObject', + { + getFoo() { + return 12; + }, + }, + { + isFoo(value) { + return value === 'foo'; + }, + } + ); const e = new ExtendedObject(); expect(e instanceof ParseObject).toBe(true); expect(e instanceof ExtendedObject).toBe(true); @@ -3319,12 +3435,16 @@ describe('ParseObject extensions', () => { it('can extend a previous extension', () => { let FeatureObject = ParseObject.extend('FeatureObject', { - foo() { return 'F'; } + foo() { + return 'F'; + }, }); let f = new FeatureObject(); expect(f.foo()).toBe('F'); FeatureObject = ParseObject.extend('FeatureObject', { - bar() { return 'B'; } + bar() { + return 'B'; + }, }); f = new FeatureObject(); expect(f.foo() + f.bar()).toBe('FB'); @@ -3332,12 +3452,12 @@ describe('ParseObject extensions', () => { it('can specify a custom initializer', () => { const InitObject = ParseObject.extend('InitObject', { - initialize: function() { + initialize: function () { this.set('field', 12); - } + }, }); - const i = new InitObject() + const i = new InitObject(); expect(i.get('field')).toBe(12); }); @@ -3408,8 +3528,7 @@ describe('ParseObject pin', () => { it('can check if pinned', async () => { const object = new ParseObject('Item'); object.id = '1234'; - mockLocalDatastore - .fromPinWithName + mockLocalDatastore.fromPinWithName .mockImplementationOnce(() => { return [object._toFullJSON()]; }) @@ -3424,13 +3543,9 @@ describe('ParseObject pin', () => { it('can fetchFromLocalDatastore', async () => { const object = new ParseObject('Item'); object.id = '123'; - mockLocalDatastore - .getKeyForObject - .mockImplementationOnce(() => 'Item_123'); + mockLocalDatastore.getKeyForObject.mockImplementationOnce(() => 'Item_123'); - mockLocalDatastore - ._serializeObject - .mockImplementationOnce(() => object._toFullJSON()); + mockLocalDatastore._serializeObject.mockImplementationOnce(() => object._toFullJSON()); await object.fetchFromLocalDatastore(); expect(mockLocalDatastore._serializeObject).toHaveBeenCalledTimes(1); @@ -3451,7 +3566,10 @@ describe('ParseObject pin', () => { const obj2 = new ParseObject('Item'); await ParseObject.pinAll([obj1, obj2]); expect(mockLocalDatastore._handlePinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handlePinAllWithName.mock.calls[0]).toEqual([DEFAULT_PIN, [obj1, obj2]]); + expect(mockLocalDatastore._handlePinAllWithName.mock.calls[0]).toEqual([ + DEFAULT_PIN, + [obj1, obj2], + ]); }); it('can unPinAll', async () => { @@ -3459,7 +3577,10 @@ describe('ParseObject pin', () => { const obj2 = new ParseObject('Item'); await ParseObject.unPinAll([obj1, obj2]); expect(mockLocalDatastore._handleUnPinAllWithName).toHaveBeenCalledTimes(1); - expect(mockLocalDatastore._handleUnPinAllWithName.mock.calls[0]).toEqual([DEFAULT_PIN, [obj1, obj2]]); + expect(mockLocalDatastore._handleUnPinAllWithName.mock.calls[0]).toEqual([ + DEFAULT_PIN, + [obj1, obj2], + ]); }); it('can unPinAllObjects', async () => { @@ -3539,21 +3660,23 @@ describe('ParseObject pin', () => { expect(error).toBe('Parse.enableLocalDatastore() must be called first'); } }); - it('gets id for new object when cascadeSave = false and singleInstance = false', (done) => { + it('gets id for new object when cascadeSave = false and singleInstance = false', done => { ParseObject.disableSingleInstance(); CoreManager.getRESTController()._setXHR( - mockXHR([{ - status: 200, - response: { - objectId: 'P5', - } - }]) + mockXHR([ + { + status: 200, + response: { + objectId: 'P5', + }, + }, + ]) ); const p = new ParseObject('Person'); - p.save(null, {cascadeSave: false}).then((obj) => { + p.save(null, { cascadeSave: false }).then(obj => { expect(obj).toBe(p); expect(obj.id).toBe('P5'); done(); }); - }) + }); }); diff --git a/src/__tests__/ParseOp-test.js b/src/__tests__/ParseOp-test.js index bbbf135cf..6f9728d45 100644 --- a/src/__tests__/ParseOp-test.js +++ b/src/__tests__/ParseOp-test.js @@ -14,26 +14,26 @@ jest.dontMock('../ParseOp'); jest.dontMock('../unique'); let localCount = 0; -const mockObject = function(className, id) { +const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { this._localId = 'local' + localCount++; } -} -mockObject.prototype._getId = function() { +}; +mockObject.prototype._getId = function () { return this.id || this._localId; -} -mockObject.fromJSON = function(json) { +}; +mockObject.fromJSON = function (json) { return new mockObject(json.className, json.objectId); -} -mockObject.registerSubclass = function() {}; +}; +mockObject.registerSubclass = function () {}; jest.setMock('../ParseObject', mockObject); -const mockRelation = function(parent, key) { +const mockRelation = function (parent, key) { this.parent = parent; this.key = key; -} +}; jest.setMock('../ParseRelation', mockRelation); const ParseRelation = require('../ParseRelation'); @@ -114,19 +114,15 @@ describe('ParseOp', () => { }); it('can create and apply Increment Ops', () => { - expect(function() { new IncrementOp(); }).toThrow( - 'Increment Op must be initialized with a numeric amount.' - ); - expect(function() { new IncrementOp('abc'); }).toThrow( - 'Increment Op must be initialized with a numeric amount.' - ); + expect(function () { + new IncrementOp(); + }).toThrow('Increment Op must be initialized with a numeric amount.'); + expect(function () { + new IncrementOp('abc'); + }).toThrow('Increment Op must be initialized with a numeric amount.'); const inc = new IncrementOp(1); - expect(inc.applyTo.bind(inc, null)).toThrow( - 'Cannot increment a non-numeric value.' - ); - expect(inc.applyTo.bind(inc, 'abc')).toThrow( - 'Cannot increment a non-numeric value.' - ); + expect(inc.applyTo.bind(inc, null)).toThrow('Cannot increment a non-numeric value.'); + expect(inc.applyTo.bind(inc, 'abc')).toThrow('Cannot increment a non-numeric value.'); expect(inc.applyTo(1)).toBe(2); expect(inc.applyTo(-40)).toBe(-39); @@ -170,9 +166,9 @@ describe('ParseOp', () => { expect(add.applyTo(null)).toEqual(['element']); expect(add.applyTo(undefined)).toEqual(['element']); - expect(function() { add.applyTo('abc'); }).toThrow( - 'Cannot add elements to a non-array value' - ); + expect(function () { + add.applyTo('abc'); + }).toThrow('Cannot add elements to a non-array value'); expect(add.applyTo([12])).toEqual([12, 'element']); expect(add.toJSON()).toEqual({ __op: 'Add', objects: ['element'] }); @@ -182,7 +178,10 @@ describe('ParseOp', () => { expect(addMany.applyTo([-2, -1, 0])).toEqual([-2, -1, 0, 1, 2, 2, 3, 4, 5]); - expect(addMany.toJSON()).toEqual({ __op: 'Add', objects: [1, 2, 2, 3, 4, 5] }); + expect(addMany.toJSON()).toEqual({ + __op: 'Add', + objects: [1, 2, 2, 3, 4, 5], + }); let merge = add.mergeWith(null); expect(merge instanceof AddOp).toBe(true); @@ -216,9 +215,9 @@ describe('ParseOp', () => { expect(add.applyTo(null)).toEqual(['element']); expect(add.applyTo(undefined)).toEqual(['element']); - expect(function() { add.applyTo('abc'); }).toThrow( - 'Cannot add elements to a non-array value' - ); + expect(function () { + add.applyTo('abc'); + }).toThrow('Cannot add elements to a non-array value'); expect(add.applyTo([12])).toEqual([12, 'element']); expect(add.applyTo([12, 'element'])).toEqual([12, 'element']); @@ -233,7 +232,7 @@ describe('ParseOp', () => { expect(addMany.toJSON()).toEqual({ __op: 'AddUnique', - objects: [1, 2, 3, 4, 5] + objects: [1, 2, 3, 4, 5], }); let merge = add.mergeWith(null); @@ -248,8 +247,7 @@ describe('ParseOp', () => { expect(merge instanceof SetOp).toBe(true); expect(merge._value).toEqual(['element']); - merge = new AddUniqueOp(['an', 'element']) - .mergeWith(new AddUniqueOp([1, 2, 'element', 3])); + merge = new AddUniqueOp(['an', 'element']).mergeWith(new AddUniqueOp([1, 2, 'element', 3])); expect(merge instanceof AddUniqueOp).toBe(true); expect(merge._value).toEqual([1, 2, 'element', 3, 'an']); @@ -264,21 +262,22 @@ describe('ParseOp', () => { ); let addObjects = new AddUniqueOp(new ParseObject('Item', 'i2')); - expect(addObjects.applyTo([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i2'), - new ParseObject('Item', 'i3'), - ])).toEqual([ + expect( + addObjects.applyTo([ + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i3'), + ]) + ).toEqual([ new ParseObject('Item', 'i1'), new ParseObject('Item', 'i2'), new ParseObject('Item', 'i3'), ]); addObjects = new AddUniqueOp(new ParseObject('Item', 'i2')); - expect(addObjects.applyTo([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i3'), - ])).toEqual([ + expect( + addObjects.applyTo([new ParseObject('Item', 'i1'), new ParseObject('Item', 'i3')]) + ).toEqual([ new ParseObject('Item', 'i1'), new ParseObject('Item', 'i3'), new ParseObject('Item', 'i2'), @@ -290,9 +289,9 @@ describe('ParseOp', () => { expect(rem.applyTo(null)).toEqual([]); expect(rem.applyTo(undefined)).toEqual([]); - expect(function() { rem.applyTo('abc'); }).toThrow( - 'Cannot remove elements from a non-array value' - ); + expect(function () { + rem.applyTo('abc'); + }).toThrow('Cannot remove elements from a non-array value'); expect(rem.applyTo([12])).toEqual([12]); expect(rem.applyTo([12, 'element'])).toEqual([12]); expect(rem.applyTo(['element', 12, 'element', 'element'])).toEqual([12]); @@ -306,7 +305,7 @@ describe('ParseOp', () => { expect(removeMany.toJSON()).toEqual({ __op: 'Remove', - objects: [1, 2, 3, 4, 5] + objects: [1, 2, 3, 4, 5], }); let merge = rem.mergeWith(null); @@ -331,30 +330,25 @@ describe('ParseOp', () => { const removeObjects = new RemoveOp(new ParseObject('Item', 'i2')); const previousOp = new RemoveOp(new ParseObject('Item', 'i5')); - expect(removeObjects.applyTo([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i2'), - new ParseObject('Item', 'i3'), - ])).toEqual([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i3'), - ]); - expect(removeObjects.applyTo([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i2'), - new ParseObject('Item', 'i2'), - new ParseObject('Item', 'i3'), - new ParseObject('Item', 'i2'), - new ParseObject('Item', 'i2'), - ])).toEqual([ - new ParseObject('Item', 'i1'), - new ParseObject('Item', 'i3'), - ]); + expect( + removeObjects.applyTo([ + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i3'), + ]) + ).toEqual([new ParseObject('Item', 'i1'), new ParseObject('Item', 'i3')]); + expect( + removeObjects.applyTo([ + new ParseObject('Item', 'i1'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i3'), + new ParseObject('Item', 'i2'), + new ParseObject('Item', 'i2'), + ]) + ).toEqual([new ParseObject('Item', 'i1'), new ParseObject('Item', 'i3')]); const merged = removeObjects.mergeWith(previousOp); - expect(merged._value).toEqual([ - new ParseObject('Item', 'i5'), - new ParseObject('Item', 'i2'), - ]); + expect(merged._value).toEqual([new ParseObject('Item', 'i5'), new ParseObject('Item', 'i2')]); }); it('can create and apply Relation Ops', () => { @@ -366,26 +360,22 @@ describe('ParseOp', () => { expect(r.relationsToAdd).toEqual([]); expect(r.relationsToRemove).toEqual([]); - expect(function() { + expect(function () { new RelationOp([new ParseObject('Item')], []); - }).toThrow( - 'You cannot add or remove an unsaved Parse Object from a relation' - ); + }).toThrow('You cannot add or remove an unsaved Parse Object from a relation'); - expect(function() { + expect(function () { const a = new ParseObject('Item'); a.id = 'I1'; const b = new ParseObject('Delivery'); b.id = 'D1'; new RelationOp([a, b]); - }).toThrow( - 'Tried to create a Relation with 2 different object types: Item and Delivery.' - ); + }).toThrow('Tried to create a Relation with 2 different object types: Item and Delivery.'); const o = new ParseObject('Item'); o.id = 'I1'; const o2 = new ParseObject('Item'); - o2.id = 'I2' + o2.id = 'I2'; r = new RelationOp([o, o, o2], []); expect(r.relationsToAdd).toEqual(['I1', 'I2']); expect(r.relationsToRemove).toEqual([]); @@ -394,8 +384,8 @@ describe('ParseOp', () => { __op: 'AddRelation', objects: [ { __type: 'Pointer', objectId: 'I1', className: 'Item' }, - { __type: 'Pointer', objectId: 'I2', className: 'Item' } - ] + { __type: 'Pointer', objectId: 'I2', className: 'Item' }, + ], }); expect(opFromJSON(r.toJSON())).toEqual(r); @@ -408,8 +398,8 @@ describe('ParseOp', () => { __op: 'RemoveRelation', objects: [ { __type: 'Pointer', objectId: 'I3', className: 'Item' }, - { __type: 'Pointer', objectId: 'I1', className: 'Item' } - ] + { __type: 'Pointer', objectId: 'I1', className: 'Item' }, + ], }); expect(opFromJSON(r2.toJSON())).toEqual(r2); @@ -429,8 +419,9 @@ describe('ParseOp', () => { const p = new ParseObject('Person'); p.id = 'P4'; const r3 = new RelationOp([p]); - expect(r3.applyTo.bind(r3, rel, { className: 'Delivery', id: 'D3' }, 'packages')) - .toThrow('Related object must be a Item, but a Person was passed in.'); + expect(r3.applyTo.bind(r3, rel, { className: 'Delivery', id: 'D3' }, 'packages')).toThrow( + 'Related object must be a Item, but a Person was passed in.' + ); const noRelation = new ParseRelation(null, null); r3.applyTo(noRelation, { className: 'Delivery', id: 'D3' }, 'packages'); @@ -450,15 +441,16 @@ describe('ParseOp', () => { ops: [ { __op: 'AddRelation', - objects: [ { __type: 'Pointer', objectId: 'I2', className: 'Item' } ] - }, { + objects: [{ __type: 'Pointer', objectId: 'I2', className: 'Item' }], + }, + { __op: 'RemoveRelation', objects: [ { __type: 'Pointer', objectId: 'I3', className: 'Item' }, - { __type: 'Pointer', objectId: 'I1', className: 'Item' } - ] - } - ] + { __type: 'Pointer', objectId: 'I1', className: 'Item' }, + ], + }, + ], }); expect(opFromJSON(merged.toJSON())).toEqual(merged); }); @@ -476,7 +468,7 @@ describe('ParseOp', () => { const r1 = new RelationOp([a, b], []); const r2 = new RelationOp([], [b]); expect(() => { - r.mergeWith(r1) + r.mergeWith(r1); }).toThrow('Related object must be of class Item, but null was passed in.'); expect(r1.mergeWith(r2)).toEqual(r1); expect(r2.mergeWith(r1)).toEqual(new RelationOp([a], [b])); diff --git a/src/__tests__/ParsePolygon-test.js b/src/__tests__/ParsePolygon-test.js index 22b6c29cb..ef500c0e7 100644 --- a/src/__tests__/ParsePolygon-test.js +++ b/src/__tests__/ParsePolygon-test.js @@ -3,7 +3,13 @@ jest.autoMockOff(); const ParseGeoPoint = require('../ParseGeoPoint').default; const ParsePolygon = require('../ParsePolygon').default; -const points = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; +const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], +]; describe('Polygon', () => { it('can initialize with points', () => { @@ -17,14 +23,20 @@ describe('Polygon', () => { new ParseGeoPoint(0, 1), new ParseGeoPoint(1, 1), new ParseGeoPoint(1, 0), - new ParseGeoPoint(0, 0) + new ParseGeoPoint(0, 0), ]; const polygon = new ParsePolygon(geopoints); expect(polygon.coordinates).toEqual(points); }); it('can set points', () => { - const newPoints = [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]; + const newPoints = [ + [0, 0], + [0, 10], + [10, 10], + [10, 0], + [0, 0], + ]; const polygon = new ParsePolygon(points); expect(polygon.coordinates).toEqual(points); @@ -49,7 +61,13 @@ describe('Polygon', () => { expect(polygon1.equals(polygon2)).toBe(true); expect(polygon1.equals(geopoint)).toBe(false); - const newPoints = [[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]; + const newPoints = [ + [0, 0], + [0, 10], + [10, 10], + [10, 0], + [0, 0], + ]; polygon1.coordinates = newPoints; expect(polygon1.equals(polygon2)).toBe(false); }); @@ -57,7 +75,7 @@ describe('Polygon', () => { it('containsPoint', () => { const polygon = new ParsePolygon(points); const outside = new ParseGeoPoint(10, 10); - const inside = new ParseGeoPoint(.5, .5); + const inside = new ParseGeoPoint(0.5, 0.5); expect(polygon.containsPoint(inside)).toBe(true); expect(polygon.containsPoint(outside)).toBe(false); @@ -65,15 +83,15 @@ describe('Polygon', () => { it('throws error on invalid input', () => { expect(() => { - new ParsePolygon() + new ParsePolygon(); }).toThrow('Coordinates must be an Array'); expect(() => { - new ParsePolygon([]) + new ParsePolygon([]); }).toThrow('Polygon must have at least 3 GeoPoints or Points'); expect(() => { - new ParsePolygon([1, 2, 3]) + new ParsePolygon([1, 2, 3]); }).toThrow('Coordinates must be an Array of GeoPoints or Points'); }); }); diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index 1d21a6d39..c5d7f86fc 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -25,12 +25,12 @@ jest.mock('uuid/v4', () => { let value = 0; return () => value++; }); -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; this.attributes = {}; }; -mockObject.registerSubclass = function() {}; -mockObject.fromJSON = function(json) { +mockObject.registerSubclass = function () {}; +mockObject.fromJSON = function (json) { const o = new mockObject(json.className); o.id = json.objectId; for (const attr in json) { @@ -74,7 +74,7 @@ describe('ParseQuery', () => { const q = new ParseQuery('Item'); expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); @@ -83,7 +83,7 @@ describe('ParseQuery', () => { const q2 = new ParseQuery(item); expect(q2.className).toBe('Item'); expect(q2.toJSON()).toEqual({ - where: {} + where: {}, }); }); @@ -94,7 +94,7 @@ describe('ParseQuery', () => { const q = new ParseQuery(ObjectFunction); expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); @@ -104,16 +104,14 @@ describe('ParseQuery', () => { const q = new ParseQuery(ObjectFunction); expect(q.className).toBe('Item'); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); it('throws when created with invalid data', () => { - expect(function() { + expect(function () { new ParseQuery(); - }).toThrow( - 'A ParseQuery must be constructed with a ParseObject or class name.' - ); + }).toThrow('A ParseQuery must be constructed with a ParseObject or class name.'); }); it('can generate equality queries', () => { @@ -121,16 +119,16 @@ describe('ParseQuery', () => { q.equalTo('size', 'medium'); expect(q.toJSON()).toEqual({ where: { - size: 'medium' - } + size: 'medium', + }, }); // Overrides old constraint q.equalTo('size', 'small'); expect(q.toJSON()).toEqual({ where: { - size: 'small' - } + size: 'small', + }, }); // equalTo('key', undefined) resolves to 'does not exist' @@ -138,9 +136,9 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { size: { - $exists: false - } - } + $exists: false, + }, + }, }); const size = 'medium'; @@ -150,7 +148,7 @@ describe('ParseQuery', () => { where: { size: 'medium', stock: true, - } + }, }); }); @@ -160,18 +158,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { size: { - $ne: 'small' - } - } + $ne: 'small', + }, + }, }); q.notEqualTo('size', 'medium'); expect(q.toJSON()).toEqual({ where: { size: { - $ne: 'medium' - } - } + $ne: 'medium', + }, + }, }); const size = 'medium'; @@ -184,8 +182,8 @@ describe('ParseQuery', () => { }, stock: { $ne: true, - } - } + }, + }, }); }); @@ -195,18 +193,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $lt: 10 - } - } + $lt: 10, + }, + }, }); q.lessThan('inStock', 4); expect(q.toJSON()).toEqual({ where: { inStock: { - $lt: 4 - } - } + $lt: 4, + }, + }, }); }); @@ -216,18 +214,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $lte: 10 - } - } + $lte: 10, + }, + }, }); q.lessThanOrEqualTo('inStock', 4); expect(q.toJSON()).toEqual({ where: { inStock: { - $lte: 4 - } - } + $lte: 4, + }, + }, }); }); @@ -237,18 +235,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } - } + $gt: 0, + }, + }, }); q.greaterThan('inStock', 100); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 100 - } - } + $gt: 100, + }, + }, }); }); @@ -258,18 +256,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gte: 0 - } - } + $gte: 0, + }, + }, }); q.greaterThanOrEqualTo('inStock', 100); expect(q.toJSON()).toEqual({ where: { inStock: { - $gte: 100 - } - } + $gte: 100, + }, + }, }); }); @@ -279,18 +277,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { size: { - $in: ['small', 'medium'] - } - } + $in: ['small', 'medium'], + }, + }, }); q.containedIn('size', ['small', 'medium', 'large']); expect(q.toJSON()).toEqual({ where: { size: { - $in: ['small', 'medium', 'large'] - } - } + $in: ['small', 'medium', 'large'], + }, + }, }); }); @@ -300,18 +298,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { size: { - $nin: ['small', 'medium'] - } - } + $nin: ['small', 'medium'], + }, + }, }); q.notContainedIn('size', ['small', 'large']); expect(q.toJSON()).toEqual({ where: { size: { - $nin: ['small', 'large'] - } - } + $nin: ['small', 'large'], + }, + }, }); }); @@ -321,18 +319,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { tags: { - $all: ['hot', 'sold-out'] - } - } + $all: ['hot', 'sold-out'], + }, + }, }); q.containsAll('tags', ['sale', 'new']); expect(q.toJSON()).toEqual({ where: { tags: { - $all: ['sale', 'new'] - } - } + $all: ['sale', 'new'], + }, + }, }); }); @@ -342,7 +340,7 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ['hot', 'sold-out'] + $containedBy: ['hot', 'sold-out'], }, }, }); @@ -351,7 +349,7 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { tags: { - $containedBy: ['sale', 'new'] + $containedBy: ['sale', 'new'], }, }, }); @@ -363,35 +361,27 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { tags: { - $all: [ - {$regex: '^\\Qho\\E'}, - {$regex: '^\\Qout\\E'} - ] - } - } + $all: [{ $regex: '^\\Qho\\E' }, { $regex: '^\\Qout\\E' }], + }, + }, }); q.containsAllStartingWith('tags', ['sal', 'ne']); expect(q.toJSON()).toEqual({ where: { tags: { - $all: [ - {$regex: '^\\Qsal\\E'}, - {$regex: '^\\Qne\\E'} - ] - } - } + $all: [{ $regex: '^\\Qsal\\E' }, { $regex: '^\\Qne\\E' }], + }, + }, }); q.containsAllStartingWith('tags', 'noArray'); expect(q.toJSON()).toEqual({ where: { tags: { - $all: [ - { $regex: '^\\QnoArray\\E' }, - ] - } - } + $all: [{ $regex: '^\\QnoArray\\E' }], + }, + }, }); }); @@ -401,9 +391,9 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $exists: true - } - } + $exists: true, + }, + }, }); }); @@ -413,9 +403,9 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $exists: false - } - } + $exists: false, + }, + }, }); }); @@ -425,9 +415,9 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $regex: 'ing$' - } - } + $regex: 'ing$', + }, + }, }); q.matches('name', /\bor\b/, 'i'); @@ -435,9 +425,9 @@ describe('ParseQuery', () => { where: { name: { $regex: '\\bor\\b', - $options: 'i' - } - } + $options: 'i', + }, + }, }); q.matches('name', /\bor\b/i); @@ -445,9 +435,9 @@ describe('ParseQuery', () => { where: { name: { $regex: '\\bor\\b', - $options: 'i' - } - } + $options: 'i', + }, + }, }); q.matches('name', /\bor\b/im); @@ -455,9 +445,9 @@ describe('ParseQuery', () => { where: { name: { $regex: '\\bor\\b', - $options: 'im' - } - } + $options: 'im', + }, + }, }); }); @@ -473,15 +463,15 @@ describe('ParseQuery', () => { $inQuery: { className: 'Item', where: { - inStock: 0 - } - } - } - } + inStock: 0, + }, + }, + }, + }, }); }); - it('can generate queries that don\'t match results from other queries', () => { + it("can generate queries that don't match results from other queries", () => { const q1 = new ParseQuery('Item'); q1.equalTo('inStock', 0); @@ -493,11 +483,11 @@ describe('ParseQuery', () => { $notInQuery: { className: 'Item', where: { - inStock: 0 - } - } - } - } + inStock: 0, + }, + }, + }, + }, }); }); @@ -515,16 +505,16 @@ describe('ParseQuery', () => { query: { className: 'Item', where: { - inStock: 0 - } - } - } - } - } + inStock: 0, + }, + }, + }, + }, + }, }); }); - it('can generate queries that don\'t match keys from other queries', () => { + it("can generate queries that don't match keys from other queries", () => { const q1 = new ParseQuery('Item'); q1.equalTo('inStock', 0); @@ -538,12 +528,12 @@ describe('ParseQuery', () => { query: { className: 'Item', where: { - inStock: 0 - } - } - } - } - } + inStock: 0, + }, + }, + }, + }, + }, }); }); @@ -557,9 +547,9 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Q or \\E' - } - } + $regex: '\\Q or \\E', + }, + }, }); // Test escaping in quote() @@ -567,18 +557,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Qslash-E \\E\\\\E\\Q\\E' - } - } + $regex: '\\Qslash-E \\E\\\\E\\Q\\E', + }, + }, }); q.contains('name', 'slash-Q \\Q'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Qslash-Q \\Q\\E' - } - } + $regex: '\\Qslash-Q \\Q\\E', + }, + }, }); }); @@ -592,18 +582,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $regex: '^\\QAbc\\E' - } - } + $regex: '^\\QAbc\\E', + }, + }, }); q.startsWith('name', 'Def'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '^\\QDef\\E' - } - } + $regex: '^\\QDef\\E', + }, + }, }); }); @@ -617,18 +607,18 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\QXYZ\\E$' - } - } + $regex: '\\QXYZ\\E$', + }, + }, }); q.endsWith('name', 'xyz'); expect(q.toJSON()).toEqual({ where: { name: { - $regex: '\\Qxyz\\E$' - } - } + $regex: '\\Qxyz\\E$', + }, + }, }); }); @@ -641,10 +631,10 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 10, - longitude: 20 - } - } - } + longitude: 20, + }, + }, + }, }); q.near('shippedTo', [30, 40]); @@ -654,10 +644,10 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 30, - longitude: 40 - } - } - } + longitude: 40, + }, + }, + }, }); // GeoPoint's internal fallback @@ -668,10 +658,10 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 0, - longitude: 0 - } - } - } + longitude: 0, + }, + }, + }, }); }); @@ -684,11 +674,11 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 20, - longitude: 40 + longitude: 40, }, - $maxDistance: 2 - } - } + $maxDistance: 2, + }, + }, }); q.withinMiles('shippedTo', [20, 30], 3958.8, true); @@ -698,11 +688,11 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 20, - longitude: 30 + longitude: 30, }, - $maxDistance: 1 - } - } + $maxDistance: 1, + }, + }, }); q.withinKilometers('shippedTo', [30, 30], 6371.0, true); @@ -712,11 +702,11 @@ describe('ParseQuery', () => { $nearSphere: { __type: 'GeoPoint', latitude: 30, - longitude: 30 + longitude: 30, }, - $maxDistance: 1 - } - } + $maxDistance: 1, + }, + }, }); }); @@ -729,11 +719,11 @@ describe('ParseQuery', () => { $geoWithin: { $centerSphere: [ [40, 20], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 2 - ] - } - } - } + 2, + ], + }, + }, + }, }); q.withinMiles('shippedTo', new ParseGeoPoint(20, 30), 3958.8, false); @@ -743,11 +733,11 @@ describe('ParseQuery', () => { $geoWithin: { $centerSphere: [ [30, 20], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 1 - ] - } - } - } + 1, + ], + }, + }, + }, }); q.withinKilometers('shippedTo', new ParseGeoPoint(30, 30), 6371.0, false); @@ -757,11 +747,11 @@ describe('ParseQuery', () => { $geoWithin: { $centerSphere: [ [30, 30], // This takes [lng, lat] vs. ParseGeoPoint [lat, lng]. - 1 - ] - } - } - } + 1, + ], + }, + }, + }, }); }); @@ -772,18 +762,21 @@ describe('ParseQuery', () => { where: { shippedTo: { $within: { - $box: [{ - __type: 'GeoPoint', - latitude: 20, - longitude: 20 - }, { - __type: 'GeoPoint', - latitude: 10, - longitude: 30 - }] - } - } - } + $box: [ + { + __type: 'GeoPoint', + latitude: 20, + longitude: 20, + }, + { + __type: 'GeoPoint', + latitude: 10, + longitude: 30, + }, + ], + }, + }, + }, }); }); @@ -795,9 +788,9 @@ describe('ParseQuery', () => { where: { inStock: { $lt: 10, - $gt: 0 - } - } + $gt: 0, + }, + }, }); q.containedIn('size', ['small', 'medium']); @@ -805,12 +798,12 @@ describe('ParseQuery', () => { where: { inStock: { $lt: 10, - $gt: 0 + $gt: 0, }, size: { - $in: ['small', 'medium'] - } - } + $in: ['small', 'medium'], + }, + }, }); }); @@ -820,10 +813,10 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'createdAt' + order: 'createdAt', }); // overrides @@ -831,31 +824,31 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'name' + order: 'name', }); q.ascending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'name' + order: 'name', }); // removes whitespace - q.ascending(' createdAt') + q.ascending(' createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'createdAt' + order: 'createdAt', }); // add additional ordering @@ -863,70 +856,70 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'createdAt,name' + order: 'createdAt,name', }); q.ascending(['a', 'b', 'c']); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'a,b,c' + order: 'a,b,c', }); q.ascending('name', 'createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: 'name,createdAt' + order: 'name,createdAt', }); q.descending('createdAt'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-createdAt' + order: '-createdAt', }); q.addAscending('name'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-createdAt,name' + order: '-createdAt,name', }); q.addDescending('a', 'b', 'c'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-createdAt,name,-a,-b,-c' + order: '-createdAt,name,-a,-b,-c', }); q.descending(['a', 'b']); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - order: '-a,-b' + order: '-a,-b', }); const q2 = new ParseQuery('Item'); @@ -946,58 +939,50 @@ describe('ParseQuery', () => { it('can establish skip counts', () => { const q = new ParseQuery('Item'); - expect(q.skip.bind(q, 'string')).toThrow( - 'You can only skip by a positive number' - ); - expect(q.skip.bind(q, -5)).toThrow( - 'You can only skip by a positive number' - ); + expect(q.skip.bind(q, 'string')).toThrow('You can only skip by a positive number'); + expect(q.skip.bind(q, -5)).toThrow('You can only skip by a positive number'); q.skip(4); expect(q.toJSON()).toEqual({ where: {}, - skip: 4 + skip: 4, }); q.equalTo('name', 'Product 5'); expect(q.toJSON()).toEqual({ where: { - name: 'Product 5' + name: 'Product 5', }, - skip: 4 + skip: 4, }); }); it('can establish result limits', () => { const q = new ParseQuery('Item'); - expect(q.limit.bind(q, 'string')).toThrow( - 'You can only set the limit to a numeric value' - ); + expect(q.limit.bind(q, 'string')).toThrow('You can only set the limit to a numeric value'); q.limit(10); expect(q.toJSON()).toEqual({ where: {}, - limit: 10 + limit: 10, }); q.limit(-1); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); it('can set withCount flag in find query', () => { const q = new ParseQuery('Item'); - expect(q.withCount.bind(q, 'string')).toThrow( - 'You can only set withCount to a boolean value' - ); + expect(q.withCount.bind(q, 'string')).toThrow('You can only set withCount to a boolean value'); q.withCount(true); expect(q.toJSON()).toEqual({ where: {}, - count: 1 + count: 1, }); q.withCount(false); expect(q.toJSON()).toEqual({ - where: {} + where: {}, }); }); @@ -1036,30 +1021,30 @@ describe('ParseQuery', () => { expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - include: 'manufacturer' + include: 'manufacturer', }); q.include('previousModel', 'nextModel'); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - include: 'manufacturer,previousModel,nextModel' + include: 'manufacturer,previousModel,nextModel', }); - q.include(['lastPurchaser', 'lastPurchase']) + q.include(['lastPurchaser', 'lastPurchase']); expect(q.toJSON()).toEqual({ where: { inStock: { - $gt: 0 - } + $gt: 0, + }, }, - include: 'manufacturer,previousModel,nextModel,lastPurchaser,lastPurchase' + include: 'manufacturer,previousModel,nextModel,lastPurchaser,lastPurchase', }); }); @@ -1082,7 +1067,7 @@ describe('ParseQuery', () => { const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: 'foo' + excludeKeys: 'foo', }); const q2 = new ParseQuery('Item'); q2.withJSON(json); @@ -1095,7 +1080,7 @@ describe('ParseQuery', () => { const json = q.toJSON(); expect(json).toEqual({ where: {}, - excludeKeys: 'foo,bar' + excludeKeys: 'foo,bar', }); const q2 = new ParseQuery('Item'); q2.withJSON(json); @@ -1133,28 +1118,26 @@ describe('ParseQuery', () => { q.select('size'); expect(q.toJSON()).toEqual({ where: {}, - keys: 'size' + keys: 'size', }); q.select('inStock', 'lastPurchase'); expect(q.toJSON()).toEqual({ where: {}, - keys: 'size,inStock,lastPurchase' + keys: 'size,inStock,lastPurchase', }); - q.select(['weight', 'color']) + q.select(['weight', 'color']); expect(q.toJSON()).toEqual({ where: {}, - keys: 'size,inStock,lastPurchase,weight,color' + keys: 'size,inStock,lastPurchase,weight,color', }); }); it('can combine queries with an OR clause', () => { const q = new ParseQuery('Item'); let q2 = new ParseQuery('Purchase'); - expect(ParseQuery.or.bind(null, q, q2)).toThrow( - 'All queries must be for the same class.' - ); + expect(ParseQuery.or.bind(null, q, q2)).toThrow('All queries must be for the same class.'); q2 = new ParseQuery('Item'); q.equalTo('size', 'medium'); @@ -1163,11 +1146,8 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.or(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $or: [ - { size: 'medium' }, - { size: 'large' } - ] - } + $or: [{ size: 'medium' }, { size: 'large' }], + }, }); // It removes limits, skips, etc @@ -1175,20 +1155,15 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.or(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $or: [ - { size: 'medium' }, - { size: 'large' } - ] - } + $or: [{ size: 'medium' }, { size: 'large' }], + }, }); }); it('can combine queries with an AND clause', () => { const q = new ParseQuery('Item'); let q2 = new ParseQuery('Purchase'); - expect(ParseQuery.and.bind(null, q, q2)).toThrow( - 'All queries must be for the same class.' - ); + expect(ParseQuery.and.bind(null, q, q2)).toThrow('All queries must be for the same class.'); q2 = new ParseQuery('Item'); q.equalTo('size', 'medium'); @@ -1197,11 +1172,8 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.and(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $and: [ - { size: 'medium' }, - { size: 'large' } - ] - } + $and: [{ size: 'medium' }, { size: 'large' }], + }, }); // It removes limits, skips, etc @@ -1209,20 +1181,15 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.and(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $and: [ - { size: 'medium' }, - { size: 'large' } - ] - } + $and: [{ size: 'medium' }, { size: 'large' }], + }, }); }); it('can combine queries with a NOR clause', () => { const q = new ParseQuery('Item'); let q2 = new ParseQuery('Purchase'); - expect(ParseQuery.nor.bind(null, q, q2)).toThrow( - 'All queries must be for the same class.', - ); + expect(ParseQuery.nor.bind(null, q, q2)).toThrow('All queries must be for the same class.'); q2 = new ParseQuery('Item'); q.equalTo('size', 'medium'); @@ -1231,10 +1198,7 @@ describe('ParseQuery', () => { let mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [ - { size: 'medium' }, - { size: 'large' }, - ], + $nor: [{ size: 'medium' }, { size: 'large' }], }, }); @@ -1243,15 +1207,12 @@ describe('ParseQuery', () => { mediumOrLarge = ParseQuery.nor(q, q2); expect(mediumOrLarge.toJSON()).toEqual({ where: { - $nor: [ - { size: 'medium' }, - { size: 'large' }, - ], + $nor: [{ size: 'medium' }, { size: 'large' }], }, }); }); - it('can get the first object of a query', (done) => { + it('can get the first object of a query', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1259,32 +1220,32 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - size: 'small' - } + size: 'small', + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: [ - { objectId: 'I1', size: 'small', name: 'Product 3' } - ] + results: [{ objectId: 'I1', size: 'small', name: 'Product 3' }], }); - } + }, }); const q = new ParseQuery('Item'); - q.equalTo('size', 'small').first().then((obj) => { - expect(obj instanceof ParseObject).toBe(true); - expect(obj.className).toBe('Item'); - expect(obj.id).toBe('I1'); - expect(obj.attributes).toEqual({ - size: 'small', - name: 'Product 3' + q.equalTo('size', 'small') + .first() + .then(obj => { + expect(obj instanceof ParseObject).toBe(true); + expect(obj.className).toBe('Item'); + expect(obj.id).toBe('I1'); + expect(obj.attributes).toEqual({ + size: 'small', + name: 'Product 3', + }); + done(); }); - done(); - }); }); - it('can pass options to a first() query', (done) => { + it('can pass options to a first() query', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1292,28 +1253,30 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - size: 'small' - } + size: 'small', + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); const q = new ParseQuery('Item'); - q.equalTo('size', 'small').first({ - useMasterKey: true, - sessionToken: '1234' - }).then((obj) => { - expect(obj).toBe(undefined); - done(); - }); + q.equalTo('size', 'small') + .first({ + useMasterKey: true, + sessionToken: '1234', + }) + .then(obj => { + expect(obj).toBe(undefined); + done(); + }); }); - it('can handle explain query', (done) => { + it('can handle explain query', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1321,31 +1284,33 @@ describe('ParseQuery', () => { expect(params).toEqual({ explain: true, where: { - size: 'small' - } + size: 'small', + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: { objectId: 'I1', size: 'small', - name: 'Product 3' + name: 'Product 3', }, }); - } + }, }); const q = new ParseQuery('Item'); q.explain(); - q.equalTo('size', 'small').find().then((result) => { - expect(result.objectId).toBe('I1'); - expect(result.size).toBe('small'); - expect(result.name).toEqual('Product 3'); - done(); - }); + q.equalTo('size', 'small') + .find() + .then(result => { + expect(result.objectId).toBe('I1'); + expect(result.size).toBe('small'); + expect(result.name).toEqual('Product 3'); + done(); + }); }); - it('can get a single object by id', (done) => { + it('can get a single object by id', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1353,32 +1318,30 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I27' - } + objectId: 'I27', + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: [ - { objectId: 'I27', size: 'large', name: 'Product 27' } - ] + results: [{ objectId: 'I27', size: 'large', name: 'Product 27' }], }); - } + }, }); const q = new ParseQuery('Item'); - q.get('I27').then((obj) => { + q.get('I27').then(obj => { expect(obj instanceof ParseObject).toBe(true); expect(obj.className).toBe('Item'); expect(obj.id).toBe('I27'); expect(obj.attributes).toEqual({ size: 'large', - name: 'Product 27' + name: 'Product 27', }); done(); }); }); - it('will error when getting a nonexistent object', (done) => { + it('will error when getting a nonexistent object', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1386,30 +1349,33 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I28' - } + objectId: 'I28', + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); const q = new ParseQuery('Item'); - q.get('I28').then(() => { - // Should not be reached - expect(true).toBe(false); - done(); - }, (err) => { - expect(err.code).toBe(ParseError.OBJECT_NOT_FOUND); - expect(err.message).toBe('Object not found.'); - done(); - }); + q.get('I28').then( + () => { + // Should not be reached + expect(true).toBe(false); + done(); + }, + err => { + expect(err.code).toBe(ParseError.OBJECT_NOT_FOUND); + expect(err.message).toBe('Object not found.'); + done(); + } + ); }); - it('can pass options to a get() query', (done) => { - const context = {a: "a"}; + it('can pass options to a get() query', done => { + const context = { a: 'a' }; CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1417,31 +1383,29 @@ describe('ParseQuery', () => { expect(params).toEqual({ limit: 1, where: { - objectId: 'I27' - } + objectId: 'I27', + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); expect(options.context).toEqual(context); return Promise.resolve({ - results: [ - { objectId: 'I27', size: 'large', name: 'Product 27' } - ] + results: [{ objectId: 'I27', size: 'large', name: 'Product 27' }], }); - } + }, }); const q = new ParseQuery('Item'); q.get('I27', { useMasterKey: true, sessionToken: '1234', - context: context + context: context, }).then(() => { done(); }); }); - it('can issue a count query', (done) => { + it('can issue a count query', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1450,25 +1414,27 @@ describe('ParseQuery', () => { limit: 0, count: 1, where: { - size: 'small' - } + size: 'small', + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [], - count: 145 + count: 145, }); - } + }, }); const q = new ParseQuery('Item'); - q.equalTo('size', 'small').count().then((count) => { - expect(count).toBe(145); - done(); - }); + q.equalTo('size', 'small') + .count() + .then(count => { + expect(count).toBe(145); + done(); + }); }); - it('can pass options to a count query', (done) => { + it('can pass options to a count query', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1477,30 +1443,31 @@ describe('ParseQuery', () => { limit: 0, count: 1, where: { - size: 'small' - } + size: 'small', + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ results: [], - count: 145 + count: 145, }); - } + }, }); - const q = new ParseQuery('Item'); - q.equalTo('size', 'small').count({ - useMasterKey: true, - sessionToken: '1234' - }).then((count) => { - expect(count).toBe(145); - done(); - }); + q.equalTo('size', 'small') + .count({ + useMasterKey: true, + sessionToken: '1234', + }) + .then(count => { + expect(count).toBe(145); + done(); + }); }); - it('can issue a query to the controller', (done) => { + it('can issue a query to the controller', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1512,8 +1479,8 @@ describe('ParseQuery', () => { order: 'createdAt', where: { size: { - $in: ['small', 'medium'] - } + $in: ['small', 'medium'], + }, }, readPreference: 'PRIMARY', includeReadPreference: 'SECONDARY', @@ -1524,9 +1491,9 @@ describe('ParseQuery', () => { results: [ { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, - ] + ], }); - } + }, }); const q = new ParseQuery('Item'); @@ -1537,24 +1504,24 @@ describe('ParseQuery', () => { .select('size', 'name') .readPreference('PRIMARY', 'SECONDARY', 'SECONDARY_PREFERRED') .find() - .then((objs) => { + .then(objs => { expect(objs.length).toBe(2); expect(objs[0] instanceof ParseObject).toBe(true); expect(objs[0].attributes).toEqual({ size: 'medium', - name: 'Product 55' + name: 'Product 55', }); expect(objs[1] instanceof ParseObject).toBe(true); expect(objs[1].attributes).toEqual({ size: 'small', - name: 'Product 89' + name: 'Product 89', }); done(); }); }); - it('can pass options to find()', (done) => { - const context = {a: "a"}; + it('can pass options to find()', done => { + const context = { a: 'a' }; CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1562,17 +1529,17 @@ describe('ParseQuery', () => { expect(params).toEqual({ where: { size: { - $in: ['small', 'medium'] - } - } + $in: ['small', 'medium'], + }, + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); expect(options.context).toEqual(context); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); const q = new ParseQuery('Item'); @@ -1580,41 +1547,42 @@ describe('ParseQuery', () => { .find({ useMasterKey: true, sessionToken: '1234', - context: context + context: context, }) - .then((objs) => { + .then(objs => { expect(objs).toEqual([]); done(); }); }); - it('can receive both count and objects from find() using withCount flag', (done) => { + it('can receive both count and objects from find() using withCount flag', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { expect(className).toBe('Item'); expect(params).toEqual({ where: {}, - count: 1 + count: 1, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ - results:[ + results: [ { objectId: '1', name: 'Product 55' }, - { objectId: '2', name: 'Product 89' } ], - count: 2 + { objectId: '2', name: 'Product 89' }, + ], + count: 2, }); - } + }, }); const q = new ParseQuery('Item'); q.withCount(true) .find({ useMasterKey: true, - sessionToken: '1234' + sessionToken: '1234', }) - .then((obj) => { + .then(obj => { expect(obj.results).toBeDefined(); expect(obj.results.length).toBe(2); expect(obj.count).toBeDefined(); @@ -1627,17 +1595,19 @@ describe('ParseQuery', () => { let findMock; beforeEach(() => { findMock = jest.fn(); - findMock.mockReturnValueOnce(Promise.resolve({ - results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - ] - })); - findMock.mockReturnValueOnce(Promise.resolve({ - results: [ - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] - })); + findMock.mockReturnValueOnce( + Promise.resolve({ + results: [ + { objectId: 'I55', size: 'medium', name: 'Product 55' }, + { objectId: 'I89', size: 'small', name: 'Product 89' }, + ], + }) + ); + findMock.mockReturnValueOnce( + Promise.resolve({ + results: [{ objectId: 'I91', size: 'small', name: 'Product 91' }], + }) + ); CoreManager.setQueryController({ aggregate() {}, find: findMock, @@ -1647,11 +1617,7 @@ describe('ParseQuery', () => { it('passes query attributes through to the REST API', async () => { const q = new ParseQuery('Item'); q.containedIn('size', ['small', 'medium']); - q.matchesKeyInQuery( - 'name', - 'productName', - new ParseQuery('Review').equalTo('stars', 5) - ); + q.matchesKeyInQuery('name', 'productName', new ParseQuery('Review').equalTo('stars', 5)); q.equalTo('valid', true); q.equalTo('arrayField', ['a', 'b']); q.select('size', 'name'); @@ -1662,7 +1628,7 @@ describe('ParseQuery', () => { expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe('Item') + expect(className).toBe('Item'); expect(params).toEqual({ limit: 100, order: 'objectId', @@ -1672,7 +1638,7 @@ describe('ParseQuery', () => { where: { arrayField: ['a', 'b'], size: { - $in: ['small', 'medium'] + $in: ['small', 'medium'], }, name: { $select: { @@ -1680,13 +1646,13 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); }); @@ -1721,7 +1687,7 @@ describe('ParseQuery', () => { const q = new ParseQuery('Item'); await q.eachBatch(() => {}, { batchSize: 2 }); expect(findMock).toHaveBeenCalledTimes(2); - }) + }); it('stops iteration when the callback returns a promise that rejects', async () => { let callCount = 0; @@ -1737,8 +1703,8 @@ describe('ParseQuery', () => { it('handles a synchronous callback', async () => { const results = []; const q = new ParseQuery('Item'); - await q.eachBatch((items) => { - items.map(item => results.push(item.attributes.size)) + await q.eachBatch(items => { + items.map(item => results.push(item.attributes.size)); }); expect(results).toEqual(['medium', 'small']); }); @@ -1746,8 +1712,8 @@ describe('ParseQuery', () => { it('handles an asynchronous callback', async () => { const results = []; const q = new ParseQuery('Item'); - await q.eachBatch((items) => { - items.map(item => results.push(item.attributes.size)) + await q.eachBatch(items => { + items.map(item => results.push(item.attributes.size)); return new Promise(resolve => setImmediate(resolve)); }); expect(results).toEqual(['medium', 'small']); @@ -1758,17 +1724,19 @@ describe('ParseQuery', () => { let findMock; beforeEach(() => { findMock = jest.fn(); - findMock.mockReturnValueOnce(Promise.resolve({ - results: [ - { objectId: 'I55', size: 'medium', name: 'Product 55' }, - { objectId: 'I89', size: 'small', name: 'Product 89' }, - ] - })); - findMock.mockReturnValueOnce(Promise.resolve({ - results: [ - { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] - })); + findMock.mockReturnValueOnce( + Promise.resolve({ + results: [ + { objectId: 'I55', size: 'medium', name: 'Product 55' }, + { objectId: 'I89', size: 'small', name: 'Product 89' }, + ], + }) + ); + findMock.mockReturnValueOnce( + Promise.resolve({ + results: [{ objectId: 'I91', size: 'small', name: 'Product 91' }], + }) + ); CoreManager.setQueryController({ aggregate() {}, find: findMock, @@ -1778,11 +1746,7 @@ describe('ParseQuery', () => { it('passes query attributes through to the REST API', async () => { const q = new ParseQuery('Item'); q.containedIn('size', ['small', 'medium']); - q.matchesKeyInQuery( - 'name', - 'productName', - new ParseQuery('Review').equalTo('stars', 5) - ); + q.matchesKeyInQuery('name', 'productName', new ParseQuery('Review').equalTo('stars', 5)); q.equalTo('valid', true); q.select('size', 'name'); q.includeAll(); @@ -1791,7 +1755,7 @@ describe('ParseQuery', () => { await q.findAll(); expect(findMock).toHaveBeenCalledTimes(1); const [className, params, options] = findMock.mock.calls[0]; - expect(className).toBe('Item') + expect(className).toBe('Item'); expect(params).toEqual({ limit: 100, order: 'objectId', @@ -1800,7 +1764,7 @@ describe('ParseQuery', () => { hint: '_id_', where: { size: { - $in: ['small', 'medium'] + $in: ['small', 'medium'], }, name: { $select: { @@ -1808,13 +1772,13 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); }); @@ -1849,7 +1813,7 @@ describe('ParseQuery', () => { const q = new ParseQuery('Item'); await q.findAll({ batchSize: 2 }); expect(findMock).toHaveBeenCalledTimes(2); - }) + }); it('Returns all objects', async () => { const q = new ParseQuery('Item'); @@ -1858,7 +1822,7 @@ describe('ParseQuery', () => { }); }); - it('can iterate over results with each()', (done) => { + it('can iterate over results with each()', done => { CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1870,7 +1834,7 @@ describe('ParseQuery', () => { include: '*', where: { size: { - $in: ['small', 'medium'] + $in: ['small', 'medium'], }, name: { $select: { @@ -1878,13 +1842,13 @@ describe('ParseQuery', () => { query: { className: 'Review', where: { - stars: 5 - } - } - } + stars: 5, + }, + }, + }, }, - valid: true - } + valid: true, + }, }); expect(options.requestTask).toBeDefined(); return Promise.resolve({ @@ -1892,18 +1856,14 @@ describe('ParseQuery', () => { { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + ], }); - } + }, }); const q = new ParseQuery('Item'); q.containedIn('size', ['small', 'medium']); - q.matchesKeyInQuery( - 'name', - 'productName', - new ParseQuery('Review').equalTo('stars', 5) - ); + q.matchesKeyInQuery('name', 'productName', new ParseQuery('Review').equalTo('stars', 5)); q.equalTo('valid', true); q.select('size', 'name'); q.includeAll(); @@ -1917,8 +1877,8 @@ describe('ParseQuery', () => { }); }); - it('can pass options to each()', (done) => { - const context = {a: "a"}; + it('can pass options to each()', done => { + const context = { a: 'a' }; CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1929,10 +1889,10 @@ describe('ParseQuery', () => { keys: 'size,name', where: { size: { - $in: ['small', 'medium'] + $in: ['small', 'medium'], }, - valid: true - } + valid: true, + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); @@ -1942,9 +1902,9 @@ describe('ParseQuery', () => { { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + ], }); - } + }, }); const q = new ParseQuery('Item'); @@ -1953,21 +1913,23 @@ describe('ParseQuery', () => { q.select('size', 'name'); let calls = 0; - q.each(() => { - calls++; - }, { - useMasterKey: true, - sessionToken: '1234', - context: context - }).then(() => { + q.each( + () => { + calls++; + }, + { + useMasterKey: true, + sessionToken: '1234', + context: context, + } + ).then(() => { expect(calls).toBe(3); done(); }); }); - - it('can pass options to each() with hint', (done) => { - const context = {a: "a"}; + it('can pass options to each() with hint', done => { + const context = { a: 'a' }; CoreManager.setQueryController({ aggregate() {}, find(className, params, options) { @@ -1978,9 +1940,9 @@ describe('ParseQuery', () => { keys: 'size,name', where: { size: { - $in: ['small', 'medium'] + $in: ['small', 'medium'], }, - valid: true + valid: true, }, hint: '_id_', }); @@ -1992,9 +1954,9 @@ describe('ParseQuery', () => { { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + ], }); - } + }, }); const q = new ParseQuery('Item'); @@ -2004,13 +1966,16 @@ describe('ParseQuery', () => { q.hint('_id_'); let calls = 0; - q.each(() => { - calls++; - }, { - useMasterKey: true, - sessionToken: '1234', - context: context - }).then(() => { + q.each( + () => { + calls++; + }, + { + useMasterKey: true, + sessionToken: '1234', + context: context, + } + ).then(() => { expect(calls).toBe(3); done(); }); @@ -2046,21 +2011,21 @@ describe('ParseQuery', () => { { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + ], }); - } + }, }); }); it('can iterate with a synchronous callback', async () => { - const callback = (object) => object.attributes.size; + const callback = object => object.attributes.size; const q = new ParseQuery('Item'); const results = await q.map(callback); expect(results).toEqual(['medium', 'small', 'small']); }); it('can iterate with an asynchronous callback', async () => { - const callback = async (object) => object.attributes.size; + const callback = async object => object.attributes.size; const q = new ParseQuery('Item'); const results = await q.map(callback); expect(results).toEqual(['medium', 'small', 'small']); @@ -2068,10 +2033,12 @@ describe('ParseQuery', () => { it('stops iteration when a rejected promise is returned', async () => { let callCount = 0; - await new ParseQuery('Item').map(() => { - callCount++; - return Promise.reject(new Error('Callback rejecting')); - }).catch(() => {}); + await new ParseQuery('Item') + .map(() => { + callCount++; + return Promise.reject(new Error('Callback rejecting')); + }) + .catch(() => {}); expect(callCount).toEqual(1); }); }); @@ -2086,9 +2053,9 @@ describe('ParseQuery', () => { { objectId: 'I55', number: 1 }, { objectId: 'I89', number: 2 }, { objectId: 'I91', number: 3 }, - ] + ], }); - } + }, }); }); @@ -2110,8 +2077,8 @@ describe('ParseQuery', () => { let callCount = 0; const callback = () => { callCount += 1; - return Promise.reject(new Error("Callback rejecting")); - } + return Promise.reject(new Error('Callback rejecting')); + }; const q = new ParseQuery('Item'); await q.reduce(callback, 0).catch(() => {}); expect(callCount).toBe(1); @@ -2123,7 +2090,7 @@ describe('ParseQuery', () => { callCount += 1; accumulator.attributes.number += object.attributes.number; return accumulator; - } + }; const q = new ParseQuery('Item'); const result = await q.reduce(callback); expect(result.id).toBe('I55'); @@ -2134,14 +2101,16 @@ describe('ParseQuery', () => { it('rejects with a TypeError when there are no results and no initial value was provided', async () => { CoreManager.setQueryController({ aggregate() {}, - find() { return Promise.resolve({ results: [] }) }, + find() { + return Promise.resolve({ results: [] }); + }, }); const q = new ParseQuery('Item'); const callback = (accumulator, object) => { accumulator.attributes.number += object.attributes.number; return accumulator; - } + }; return expect(q.reduce(callback)).rejects.toThrow(TypeError); }); }); @@ -2156,21 +2125,21 @@ describe('ParseQuery', () => { { objectId: 'I55', size: 'medium', name: 'Product 55' }, { objectId: 'I89', size: 'small', name: 'Product 89' }, { objectId: 'I91', size: 'small', name: 'Product 91' }, - ] + ], }); - } + }, }); }); it('can iterate results with a synchronous callback', async () => { - const callback = (object) => object.attributes.size === 'small'; + const callback = object => object.attributes.size === 'small'; const q = new ParseQuery('Item'); const results = await q.filter(callback); expect(results.length).toBe(2); }); it('can iterate results with an async callback', async () => { - const callback = async (object) => object.attributes.size === 'small'; + const callback = async object => object.attributes.size === 'small'; const q = new ParseQuery('Item'); const results = await q.filter(callback); expect(results.length).toBe(2); @@ -2188,17 +2157,20 @@ describe('ParseQuery', () => { }); }); - it('returns an error when iterating over an invalid query', (done) => { + it('returns an error when iterating over an invalid query', done => { const q = new ParseQuery('Item'); q.limit(10); - q.each(() => {}).then(() => { - // this should not be reached - expect(true).toBe(false); - done(); - }, (err) => { - expect(err).toBe('Cannot iterate on a query with sort, skip, or limit.'); - done(); - }); + q.each(() => {}).then( + () => { + // this should not be reached + expect(true).toBe(false); + done(); + }, + err => { + expect(err).toBe('Cannot iterate on a query with sort, skip, or limit.'); + done(); + } + ); }); it('rewrites User queries when the rewrite is enabled', () => { @@ -2210,48 +2182,43 @@ describe('ParseQuery', () => { expect(q.className).toBe('User'); }); - it('does not override the className if it comes from the server', (done) => { + it('does not override the className if it comes from the server', done => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [ - { className: 'Product', objectId: 'P40', name: 'Product 40' }, - ] + results: [{ className: 'Product', objectId: 'P40', name: 'Product 40' }], }); - } + }, }); const q = new ParseQuery('Item'); - q.find().then((results) => { + q.find().then(results => { expect(results[0].className).toBe('Product'); done(); }); }); - it('can override the className with a name from the server', (done) => { + it('can override the className with a name from the server', done => { CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [ - { objectId: 'P41', name: 'Product 41' }, - ], - className: 'Product' + results: [{ objectId: 'P41', name: 'Product 41' }], + className: 'Product', }); - } + }, }); const q = new ParseQuery('Item'); - q.find().then((results) => { + q.find().then(results => { expect(results[0].className).toBe('Product'); done(); }); }); - - it('overrides cached object with query results', (done) => { - jest.dontMock("../ParseObject"); + it('overrides cached object with query results', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2263,42 +2230,45 @@ describe('ParseQuery', () => { objectId: 'T01', name: 'Name', other: 'other', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; - q.find().then((results) => { - testObject = results[0]; - - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); - - objectToReturn = { objectId: 'T01', name: 'Name2'}; - const q2 = new ParseQuery("Thing"); - return q2.find(); - }).then((results) => { - expect(results[0].get("name")).toBe("Name2"); - expect(results[0].has("other")).toBe(false); - }).then(() => { - expect(testObject.get("name")).toBe("Name2"); - expect(testObject.has("other")).toBe(false); - done(); - }); + q.find() + .then(results => { + testObject = results[0]; + + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); + + objectToReturn = { objectId: 'T01', name: 'Name2' }; + const q2 = new ParseQuery('Thing'); + return q2.find(); + }) + .then(results => { + expect(results[0].get('name')).toBe('Name2'); + expect(results[0].has('other')).toBe(false); + }) + .then(() => { + expect(testObject.get('name')).toBe('Name2'); + expect(testObject.has('other')).toBe(false); + done(); + }); }); - it('does not override unselected fields with select query results', (done) => { - jest.dontMock("../ParseObject"); + it('does not override unselected fields with select query results', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2311,59 +2281,70 @@ describe('ParseQuery', () => { name: 'Name', other: 'other', tbd: 'exists', - className:"Thing", + className: 'Thing', createdAt: '2017-01-10T10:00:00Z', - subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"} + subObject: { key1: 'value', key2: 'value2', key3: 'thisWillGoAway' }, }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; - return q.find().then((results) => { - testObject = results[0]; - - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); - expect(testObject.has("tbd")).toBe(true); - expect(testObject.get("subObject").key1).toBe("value"); - expect(testObject.get("subObject").key2).toBe("value2"); - expect(testObject.get("subObject").key3).toBe("thisWillGoAway"); - - const q2 = new ParseQuery("Thing"); - q2.select("other", "tbd", "subObject.key1", "subObject.key3"); - objectToReturn = { objectId: 'T01', other: 'other2', subObject:{key1:"updatedValue"}}; - return q2.find(); - }).then((results) => { - expect(results[0].get("name")).toBe("Name"); //query didn't select this - expect(results[0].get("other")).toBe("other2"); //query selected and updated this - expect(results[0].has("tbd")).toBe(false); //query selected this and it wasn't returned - //sub-objects should work similarly - expect(results[0].get("subObject").key1).toBe("updatedValue"); - expect(results[0].get("subObject").key2).toBe("value2"); - expect(results[0].get("subObject").key3).toBeUndefined(); - }).then(() => { - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other2"); - expect(testObject.has("tbd")).toBe(false); - expect(testObject.get("subObject").key1).toBe("updatedValue"); - expect(testObject.get("subObject").key2).toBe("value2"); - expect(testObject.get("subObject").key3).toBeUndefined(); - done(); - }, (error) => { - done.fail(error); - }); + return q + .find() + .then(results => { + testObject = results[0]; + + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); + expect(testObject.has('tbd')).toBe(true); + expect(testObject.get('subObject').key1).toBe('value'); + expect(testObject.get('subObject').key2).toBe('value2'); + expect(testObject.get('subObject').key3).toBe('thisWillGoAway'); + + const q2 = new ParseQuery('Thing'); + q2.select('other', 'tbd', 'subObject.key1', 'subObject.key3'); + objectToReturn = { + objectId: 'T01', + other: 'other2', + subObject: { key1: 'updatedValue' }, + }; + return q2.find(); + }) + .then(results => { + expect(results[0].get('name')).toBe('Name'); //query didn't select this + expect(results[0].get('other')).toBe('other2'); //query selected and updated this + expect(results[0].has('tbd')).toBe(false); //query selected this and it wasn't returned + //sub-objects should work similarly + expect(results[0].get('subObject').key1).toBe('updatedValue'); + expect(results[0].get('subObject').key2).toBe('value2'); + expect(results[0].get('subObject').key3).toBeUndefined(); + }) + .then( + () => { + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other2'); + expect(testObject.has('tbd')).toBe(false); + expect(testObject.get('subObject').key1).toBe('updatedValue'); + expect(testObject.get('subObject').key2).toBe('value2'); + expect(testObject.get('subObject').key3).toBeUndefined(); + done(); + }, + error => { + done.fail(error); + } + ); }); - it('overrides cached object with first() results', (done) => { - jest.dontMock("../ParseObject"); + it('overrides cached object with first() results', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2375,42 +2356,45 @@ describe('ParseQuery', () => { objectId: 'T01', name: 'Name', other: 'other', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; - q.first().then((result) => { - testObject = result; - - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); - - objectToReturn = { objectId: 'T01', name: 'Name2'}; - const q2 = new ParseQuery("Thing"); - return q2.first(); - }).then((result) => { - expect(result.get("name")).toBe("Name2"); - expect(result.has("other")).toBe(false); - }).then(() => { - expect(testObject.get("name")).toBe("Name2"); - expect(testObject.has("other")).toBe(false); - done(); - }); + q.first() + .then(result => { + testObject = result; + + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); + + objectToReturn = { objectId: 'T01', name: 'Name2' }; + const q2 = new ParseQuery('Thing'); + return q2.first(); + }) + .then(result => { + expect(result.get('name')).toBe('Name2'); + expect(result.has('other')).toBe(false); + }) + .then(() => { + expect(testObject.get('name')).toBe('Name2'); + expect(testObject.has('other')).toBe(false); + done(); + }); }); - it('does not override unselected fields for first() on select query', (done) => { - jest.dontMock("../ParseObject"); + it('does not override unselected fields for first() on select query', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2423,8 +2407,8 @@ describe('ParseQuery', () => { name: 'Name', other: 'other', tbd: 'exists', - className:"Thing", - subObject: {key1:"value", key2:"value2", key3:"thisWillGoAway"}, + className: 'Thing', + subObject: { key1: 'value', key2: 'value2', key3: 'thisWillGoAway' }, createdAt: '2017-01-10T10:00:00Z', }; @@ -2432,43 +2416,54 @@ describe('ParseQuery', () => { aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; - return q.first().then((result) => { - testObject = result; - - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other"); - expect(testObject.has("tbd")).toBe(true); - - const q2 = new ParseQuery("Thing"); - q2.select("other", "tbd", "subObject.key1", "subObject.key3"); - objectToReturn = { objectId: 'T01', other: 'other2', subObject:{key1:"updatedValue"}}; - return q2.first(); - }).then((result) => { - expect(result.get("name")).toBe("Name"); //query didn't select this - expect(result.get("other")).toBe("other2"); //query selected and updated this - expect(result.has("tbd")).toBe(false); //query selected this and it wasn't returned - //sub-objects should work similarly - expect(result.get("subObject").key1).toBe("updatedValue"); - expect(result.get("subObject").key2).toBe("value2"); - expect(result.get("subObject").key3).toBeUndefined(); - }).then(() => { - expect(testObject.get("name")).toBe("Name"); - expect(testObject.get("other")).toBe("other2"); - expect(testObject.has("tbd")).toBe(false); - expect(testObject.get("subObject").key1).toBe("updatedValue"); - expect(testObject.get("subObject").key2).toBe("value2"); - expect(testObject.get("subObject").key3).toBeUndefined(); - done(); - }, (error) => { - done.fail(error); - }); + return q + .first() + .then(result => { + testObject = result; + + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other'); + expect(testObject.has('tbd')).toBe(true); + + const q2 = new ParseQuery('Thing'); + q2.select('other', 'tbd', 'subObject.key1', 'subObject.key3'); + objectToReturn = { + objectId: 'T01', + other: 'other2', + subObject: { key1: 'updatedValue' }, + }; + return q2.first(); + }) + .then(result => { + expect(result.get('name')).toBe('Name'); //query didn't select this + expect(result.get('other')).toBe('other2'); //query selected and updated this + expect(result.has('tbd')).toBe(false); //query selected this and it wasn't returned + //sub-objects should work similarly + expect(result.get('subObject').key1).toBe('updatedValue'); + expect(result.get('subObject').key2).toBe('value2'); + expect(result.get('subObject').key3).toBeUndefined(); + }) + .then( + () => { + expect(testObject.get('name')).toBe('Name'); + expect(testObject.get('other')).toBe('other2'); + expect(testObject.has('tbd')).toBe(false); + expect(testObject.get('subObject').key1).toBe('updatedValue'); + expect(testObject.get('subObject').key2).toBe('value2'); + expect(testObject.get('subObject').key3).toBeUndefined(); + done(); + }, + error => { + done.fail(error); + } + ); }); it('restores queries from json representation', () => { @@ -2496,12 +2491,12 @@ describe('ParseQuery', () => { order: 'a,b,c', skip: 4, where: { - size: 'medium' - } + size: 'medium', + }, }); }); - it('can issue a distinct query', (done) => { + it('can issue a distinct query', done => { CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2509,25 +2504,27 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small' - } + size: 'small', + }, }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: ['L'], }); - } + }, }); const q = new ParseQuery('Item'); - q.equalTo('size', 'small').distinct('size').then((results) => { - expect(results[0]).toBe('L'); - done(); - }); + q.equalTo('size', 'small') + .distinct('size') + .then(results => { + expect(results[0]).toBe('L'); + done(); + }); }); - it('can pass options to a distinct query', (done) => { + it('can pass options to a distinct query', done => { CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2535,29 +2532,30 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small' - } + size: 'small', + }, }); expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: ['L'] + results: ['L'], }); - } + }, }); - const q = new ParseQuery('Item'); - q.equalTo('size', 'small').distinct('size', { - sessionToken: '1234' - }).then((results) => { - expect(results[0]).toBe('L'); - done(); - }); + q.equalTo('size', 'small') + .distinct('size', { + sessionToken: '1234', + }) + .then(results => { + expect(results[0]).toBe('L'); + done(); + }); }); - it('can pass options to a distinct query with hint', (done) => { + it('can pass options to a distinct query with hint', done => { CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2565,7 +2563,7 @@ describe('ParseQuery', () => { expect(params).toEqual({ distinct: 'size', where: { - size: 'small' + size: 'small', }, hint: '_id_', }); @@ -2573,19 +2571,21 @@ describe('ParseQuery', () => { expect(options.sessionToken).toEqual('1234'); expect(options.requestTask).toBeDefined(); return Promise.resolve({ - results: ['L'] + results: ['L'], }); - } + }, }); - const q = new ParseQuery('Item'); - q.equalTo('size', 'small').hint('_id_').distinct('size', { - sessionToken: '1234' - }).then((results) => { - expect(results[0]).toBe('L'); - done(); - }); + q.equalTo('size', 'small') + .hint('_id_') + .distinct('size', { + sessionToken: '1234', + }) + .then(results => { + expect(results[0]).toBe('L'); + done(); + }); }); it('can issue a query to the controller', () => { @@ -2604,11 +2604,8 @@ describe('ParseQuery', () => { expect(query._subqueryReadPreference).toBe('SECONDARY_PREFERRED'); }); - - it('can issue an aggregate query with array pipeline', (done) => { - const pipeline = [ - { group: { objectId: '$name' } } - ]; + it('can issue an aggregate query with array pipeline', done => { + const pipeline = [{ group: { objectId: '$name' } }]; CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2619,20 +2616,18 @@ describe('ParseQuery', () => { return Promise.resolve({ results: [], }); - } + }, }); const q = new ParseQuery('Item'); - q.aggregate(pipeline).then((results) => { + q.aggregate(pipeline).then(results => { expect(results).toEqual([]); done(); }); }); - it('aggregate query array pipeline with equalTo', (done) => { - const pipeline = [ - { group: { objectId: '$name' } } - ]; + it('aggregate query array pipeline with equalTo', done => { + const pipeline = [{ group: { objectId: '$name' } }]; MockRESTController.request.mockImplementationOnce(() => { return Promise.resolve({ results: [], @@ -2640,15 +2635,15 @@ describe('ParseQuery', () => { }); const q = new ParseQuery('Item'); q.equalTo('name', 'foo'); - q.aggregate(pipeline).then((results) => { + q.aggregate(pipeline).then(results => { expect(results).toEqual([]); done(); }); }); - it('aggregate query object pipeline with equalTo', (done) => { + it('aggregate query object pipeline with equalTo', done => { const pipeline = { - group: { objectId: '$name' } + group: { objectId: '$name' }, }; MockRESTController.request.mockImplementationOnce(() => { return Promise.resolve({ @@ -2657,15 +2652,15 @@ describe('ParseQuery', () => { }); const q = new ParseQuery('Item'); q.equalTo('name', 'foo'); - q.aggregate(pipeline).then((results) => { + q.aggregate(pipeline).then(results => { expect(results).toEqual([]); done(); }); }); - it('can issue an aggregate query with object pipeline', (done) => { + it('can issue an aggregate query with object pipeline', done => { const pipeline = { - group: { objectId: '$name' } + group: { objectId: '$name' }, }; CoreManager.setQueryController({ find() {}, @@ -2677,31 +2672,31 @@ describe('ParseQuery', () => { return Promise.resolve({ results: [], }); - } + }, }); const q = new ParseQuery('Item'); - q.aggregate(pipeline).then((results) => { + q.aggregate(pipeline).then(results => { expect(results).toEqual([]); done(); }); }); - it('cannot issue an aggregate query with invalid pipeline', (done) => { + it('cannot issue an aggregate query with invalid pipeline', done => { const pipeline = 1234; CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { expect(className).toBe('Item'); expect(params).toEqual({ - group: { objectId: '$name' } + group: { objectId: '$name' }, }); expect(options.useMasterKey).toEqual(true); expect(options.requestTask).toBeDefined(); return Promise.resolve({ results: [], }); - } + }, }); try { @@ -2712,10 +2707,8 @@ describe('ParseQuery', () => { } }); - it('can pass options to an aggregate query', (done) => { - const pipeline = [ - { group: { objectId: '$name' } } - ]; + it('can pass options to an aggregate query', done => { + const pipeline = [{ group: { objectId: '$name' } }]; CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2724,21 +2717,21 @@ describe('ParseQuery', () => { expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); const q = new ParseQuery('Item'); q.aggregate(pipeline, { - sessionToken: '1234' - }).then((results) => { + sessionToken: '1234', + }).then(results => { expect(results).toEqual([]); done(); }); }); - it('can issue an aggregate query with read preference', async() => { + it('can issue an aggregate query with read preference', async () => { // Override controller CoreManager.setQueryController({ find() {}, @@ -2747,9 +2740,9 @@ describe('ParseQuery', () => { expect(params.readPreference).toEqual('SECONDARY'); expect(options.useMasterKey).toEqual(true); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); // Query const q = new ParseQuery('Item'); @@ -2759,10 +2752,8 @@ describe('ParseQuery', () => { expect(results).toEqual([]); }); - it('can pass options to an aggregate query with hint', (done) => { - const pipeline = [ - { group: { objectId: '$name' } } - ]; + it('can pass options to an aggregate query with hint', done => { + const pipeline = [{ group: { objectId: '$name' } }]; CoreManager.setQueryController({ find() {}, aggregate(className, params, options) { @@ -2772,18 +2763,20 @@ describe('ParseQuery', () => { expect(options.useMasterKey).toEqual(true); expect(options.sessionToken).toEqual('1234'); return Promise.resolve({ - results: [] + results: [], }); - } + }, }); const q = new ParseQuery('Item'); - q.hint('_id_').aggregate(pipeline, { - sessionToken: '1234' - }).then((results) => { - expect(results).toEqual([]); - done(); - }); + q.hint('_id_') + .aggregate(pipeline, { + sessionToken: '1234', + }) + .then(results => { + expect(results).toEqual([]); + done(); + }); }); it('can cancel query', async () => { @@ -2792,10 +2785,10 @@ describe('ParseQuery', () => { }; CoreManager.setQueryController({ - find: function(name, params, options) { + find: function (name, params, options) { options.requestTask(mockRequestTask); return Promise.resolve({ - results: [] + results: [], }); }, aggregate: () => {}, @@ -2816,8 +2809,8 @@ describe('ParseQuery', () => { expect(mockRequestTask.abort).toHaveBeenCalledTimes(1); }); - it('selecting sub-objects does not inject objects when sub-object does not exist', (done) => { - jest.dontMock("../ParseObject"); + it('selecting sub-objects does not inject objects when sub-object does not exist', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2829,38 +2822,43 @@ describe('ParseQuery', () => { objectId: 'T01', name: 'Name', tbd: 'exists', - className:"Thing", - createdAt: '2017-01-10T10:00:00Z' + className: 'Thing', + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); - q.select("other", "tbd", "subObject.key1") + const q = new ParseQuery('Thing'); + q.select('other', 'tbd', 'subObject.key1'); let testObject; - return q.find().then((results) => { - testObject = results[0]; - - expect(testObject.get("name")).toBe("Name"); - expect(testObject.has("other")).toBe(false); - expect(testObject.has("subObject")).toBe(false); + return q + .find() + .then(results => { + testObject = results[0]; - }).then(() => { - done(); - }, (error) => { - done.fail(error); - }); + expect(testObject.get('name')).toBe('Name'); + expect(testObject.has('other')).toBe(false); + expect(testObject.has('subObject')).toBe(false); + }) + .then( + () => { + done(); + }, + error => { + done.fail(error); + } + ); }); - it('removes missing sub objects from the cached object when they are selected', (done) => { - jest.dontMock("../ParseObject"); + it('removes missing sub objects from the cached object when they are selected', done => { + jest.dontMock('../ParseObject'); jest.resetModules(); ParseObject = require('../ParseObject').default; CoreManager = require('../CoreManager'); @@ -2872,50 +2870,68 @@ describe('ParseQuery', () => { objectId: 'T01', name: 'Name', tbd: 'exists', - className:"Thing", - subObject1: {foo:"bar"}, - subObject2: {foo:"bar"}, - subObject3: {foo:"bar"}, - subObject5: {subSubObject:{foo:"foo", bar:"bar"}}, - createdAt: '2017-01-10T10:00:00Z' + className: 'Thing', + subObject1: { foo: 'bar' }, + subObject2: { foo: 'bar' }, + subObject3: { foo: 'bar' }, + subObject5: { subSubObject: { foo: 'foo', bar: 'bar' } }, + createdAt: '2017-01-10T10:00:00Z', }; CoreManager.setQueryController({ aggregate() {}, find() { return Promise.resolve({ - results: [objectToReturn] + results: [objectToReturn], }); - } + }, }); - const q = new ParseQuery("Thing"); + const q = new ParseQuery('Thing'); let testObject; - return q.find().then((results) => { - testObject = results[0]; - - expect(testObject.has("subObject1")).toBe(true); - expect(testObject.has("subObject2")).toBe(true); - expect(testObject.has("subObject3")).toBe(true); - expect(testObject.has("subObject4")).toBe(false); - - const q2 = new ParseQuery("Thing"); - q2.select("name","subObject1", "subObject2.foo", "subObject4.foo", "subObject5.subSubObject.foo"); - objectToReturn = { objectId: 'T01', name:"Name", subObject4: {foo:"bar"}, subObject5: {subSubObject:{}}}; - return q2.find(); - }).then(()=>{ - expect(testObject.has("subObject1")).toBe(false); //selected and not returned - expect(testObject.has("subObject2")).toBe(false); //selected and not returned - expect(testObject.has("subObject3")).toBe(true); //not selected, so should still be there - expect(testObject.has("subObject4")).toBe(true); //selected and just added - expect(testObject.has("subObject5")).toBe(true); - expect(testObject.get("subObject5").subSubObject).toBeDefined(); - expect(testObject.get("subObject5").subSubObject.bar).toBeDefined(); //not selected but a sibiling was, so should still be there - }).then(() => { - done(); - }, (error) => { - done.fail(error); - }); + return q + .find() + .then(results => { + testObject = results[0]; + + expect(testObject.has('subObject1')).toBe(true); + expect(testObject.has('subObject2')).toBe(true); + expect(testObject.has('subObject3')).toBe(true); + expect(testObject.has('subObject4')).toBe(false); + + const q2 = new ParseQuery('Thing'); + q2.select( + 'name', + 'subObject1', + 'subObject2.foo', + 'subObject4.foo', + 'subObject5.subSubObject.foo' + ); + objectToReturn = { + objectId: 'T01', + name: 'Name', + subObject4: { foo: 'bar' }, + subObject5: { subSubObject: {} }, + }; + return q2.find(); + }) + .then(() => { + expect(testObject.has('subObject1')).toBe(false); //selected and not returned + expect(testObject.has('subObject2')).toBe(false); //selected and not returned + expect(testObject.has('subObject3')).toBe(true); //not selected, so should still be there + expect(testObject.has('subObject4')).toBe(true); //selected and just added + expect(testObject.has('subObject5')).toBe(true); + expect(testObject.get('subObject5').subSubObject).toBeDefined(); + expect(testObject.get('subObject5').subSubObject.bar).toBeDefined(); //not selected but a sibiling was, so should still be there + }) + .then( + () => { + done(); + }, + error => { + done.fail(error); + } + ); }); it('full text search', () => { @@ -2927,11 +2943,11 @@ describe('ParseQuery', () => { size: { $text: { $search: { - $term: "small" - } - } - } - } + $term: 'small', + }, + }, + }, + }, }); }); @@ -2946,44 +2962,52 @@ describe('ParseQuery', () => { size: { $text: { $search: { - $term: "medium", - } - } - } + $term: 'medium', + }, + }, + }, }, - keys : "$score", - order : "$score" + keys: '$score', + order: '$score', }); }); - it('full text search key required', (done) => { + it('full text search key required', done => { const query = new ParseQuery('Item'); expect(() => query.fullText()).toThrow('A key is required.'); done(); }); - it('full text search value required', (done) => { + it('full text search value required', done => { const query = new ParseQuery('Item'); expect(() => query.fullText('key')).toThrow('A search term is required'); done(); }); - it('full text search value must be string', (done) => { + it('full text search value must be string', done => { const query = new ParseQuery('Item'); - expect(() => query.fullText('key', [])).toThrow('The value being searched for must be a string.'); + expect(() => query.fullText('key', [])).toThrow( + 'The value being searched for must be a string.' + ); done(); }); - it('full text search invalid option', (done) => { + it('full text search invalid option', done => { const query = new ParseQuery('Item'); - expect(() => query.fullText('size', 'medium', { unknown: 'throwOption' })).toThrow('Unknown option: unknown'); + expect(() => query.fullText('size', 'medium', { unknown: 'throwOption' })).toThrow( + 'Unknown option: unknown' + ); done(); }); it('full text search with all parameters', () => { const query = new ParseQuery('Item'); - query.fullText('size', 'medium', { language: 'en', caseSensitive: false, diacriticSensitive: true }); + query.fullText('size', 'medium', { + language: 'en', + caseSensitive: false, + diacriticSensitive: true, + }); expect(query.toJSON()).toEqual({ where: { @@ -3022,7 +3046,6 @@ describe('ParseQuery', () => { order: '$score', }); }); - }); describe('ParseQuery LocalDatastore', () => { @@ -3032,9 +3055,7 @@ describe('ParseQuery LocalDatastore', () => { }); it('can query from local datastore', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); @@ -3045,9 +3066,7 @@ describe('ParseQuery LocalDatastore', () => { }); it('can query from default pin', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); @@ -3062,9 +3081,7 @@ describe('ParseQuery LocalDatastore', () => { }); it('can query from pin with name', () => { - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); const q = new ParseQuery('Item'); expect(q._queriesLocalDatastore).toBe(false); @@ -3118,13 +3135,13 @@ describe('ParseQuery LocalDatastore', () => { objectId: 'objectId3', }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementationOnce(() => [obj1, obj2, obj3]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); const q = new ParseQuery('Item'); q.equalTo('count', 2); @@ -3150,13 +3167,13 @@ describe('ParseQuery LocalDatastore', () => { objectId: 'objectId3', }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementationOnce(() => [obj1, obj2, obj3]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); const q = new ParseQuery('Item'); q.equalTo('count', 2); @@ -3182,13 +3199,13 @@ describe('ParseQuery LocalDatastore', () => { objectId: 'objectId3', }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementationOnce(() => [obj1, obj2, obj3]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => [ + obj1, + obj2, + obj3, + ]); - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); let q = new ParseQuery('Item'); q.fromLocalDatastore(); @@ -3196,13 +3213,9 @@ describe('ParseQuery LocalDatastore', () => { expect(result.id).toEqual(obj1.objectId); jest.clearAllMocks(); - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementationOnce(() => []); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementationOnce(() => []); - mockLocalDatastore - .checkIfEnabled - .mockImplementationOnce(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementationOnce(() => true); q = new ParseQuery('Item'); q.fromLocalDatastore(); @@ -3238,13 +3251,9 @@ describe('ParseQuery LocalDatastore', () => { updatedAt: new Date('2018-08-12T00:00:00.000Z'), }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => [obj1, obj2, obj3]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj2, obj3]); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); let q = new ParseQuery('Item'); q.ascending('number'); @@ -3326,13 +3335,14 @@ describe('ParseQuery LocalDatastore', () => { string: 'd', }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => [obj1, obj2, obj3, obj4]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [ + obj1, + obj2, + obj3, + obj4, + ]); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); let q = new ParseQuery('Item'); q.ascending('number,string'); @@ -3404,13 +3414,9 @@ describe('ParseQuery LocalDatastore', () => { string: 'b', }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => [obj1, obj2]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1, obj2]); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); let q = new ParseQuery('Item'); q.limit(0); @@ -3467,13 +3473,9 @@ describe('ParseQuery LocalDatastore', () => { }; const objects = [obj1, obj2, obj3]; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => objects); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => objects); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); let q = new ParseQuery('Item'); q.skip(0); @@ -3545,13 +3547,9 @@ describe('ParseQuery LocalDatastore', () => { }; const objects = [obj1, obj2, obj3]; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => objects); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => objects); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); let q = new ParseQuery('Item'); q.skip(0); @@ -3621,13 +3619,9 @@ describe('ParseQuery LocalDatastore', () => { bar: 1, }; - mockLocalDatastore - ._serializeObjectsFromPinName - .mockImplementation(() => [obj1]); + mockLocalDatastore._serializeObjectsFromPinName.mockImplementation(() => [obj1]); - mockLocalDatastore - .checkIfEnabled - .mockImplementation(() => true); + mockLocalDatastore.checkIfEnabled.mockImplementation(() => true); const q = new ParseQuery('Item'); q.select('foo'); @@ -3638,10 +3632,10 @@ describe('ParseQuery LocalDatastore', () => { it('can subscribe to query if client is already open', async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return false; }, - subscribe: function(query, sessionToken) { + subscribe: function (query, sessionToken) { const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; @@ -3652,14 +3646,14 @@ describe('ParseQuery LocalDatastore', () => { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); @@ -3670,11 +3664,11 @@ describe('ParseQuery LocalDatastore', () => { it('can subscribe to query if client is not open', async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return true; }, - open: function() {}, - subscribe: function(query, sessionToken) { + open: function () {}, + subscribe: function (query, sessionToken) { const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; @@ -3685,14 +3679,14 @@ describe('ParseQuery LocalDatastore', () => { return Promise.resolve({ getSessionToken() { return 'token'; - } + }, }); - } + }, }); CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); @@ -3703,11 +3697,11 @@ describe('ParseQuery LocalDatastore', () => { it('can subscribe to query without sessionToken', async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return true; }, - open: function() {}, - subscribe: function(query, sessionToken) { + open: function () {}, + subscribe: function (query, sessionToken) { const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; @@ -3716,12 +3710,12 @@ describe('ParseQuery LocalDatastore', () => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(null); - } + }, }); CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); const query = new ParseQuery('TestObject'); const subscription = await query.subscribe(); @@ -3732,11 +3726,11 @@ describe('ParseQuery LocalDatastore', () => { it('can subscribe to query with sessionToken parameter', async () => { const mockLiveQueryClient = { - shouldOpen: function() { + shouldOpen: function () { return true; }, - open: function() {}, - subscribe: function(query, sessionToken) { + open: function () {}, + subscribe: function (query, sessionToken) { const subscription = new LiveQuerySubscription('0', query, sessionToken); subscription.subscribePromise.resolve(); return subscription; @@ -3745,12 +3739,12 @@ describe('ParseQuery LocalDatastore', () => { CoreManager.set('UserController', { currentUserAsync() { return Promise.resolve(null); - } + }, }); CoreManager.set('LiveQueryController', { getDefaultLiveQueryClient() { return Promise.resolve(mockLiveQueryClient); - } + }, }); const query = new ParseQuery('TestObject'); const subscription = await query.subscribe('r:test'); diff --git a/src/__tests__/ParseRelation-test.js b/src/__tests__/ParseRelation-test.js index 7c226eeb1..c2514ca90 100644 --- a/src/__tests__/ParseRelation-test.js +++ b/src/__tests__/ParseRelation-test.js @@ -13,11 +13,11 @@ jest.dontMock('../ParseOp'); jest.dontMock('../unique'); const mockStore = {}; -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; this.ops = {}; }; -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; mockObject.prototype = { _getId() { return this.id; @@ -38,11 +38,7 @@ mockObject.prototype = { return new ParseRelation(this, key); }, get(key) { - return this.op(key).applyTo( - null, - { className: this.className, id: this.id }, - key - ); + return this.op(key).applyTo(null, { className: this.className, id: this.id }, key); }, op(key) { let finalOp = undefined; @@ -50,11 +46,11 @@ mockObject.prototype = { finalOp = mockStore[this.id][key][i].mergeWith(finalOp); } return finalOp; - } + }, }; jest.setMock('../ParseObject', mockObject); -const mockQuery = function(className) { +const mockQuery = function (className) { this.className = className; this.where = {}; this._extraOptions = {}; @@ -63,7 +59,7 @@ mockQuery.prototype = { _addCondition(key, comparison, value) { this.where[key] = this.where[key] || {}; this.where[key][comparison] = value; - } + }, }; jest.setMock('../ParseQuery', mockQuery); @@ -90,13 +86,11 @@ describe('ParseRelation', () => { expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'AddRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D1', className: 'Delivery' }], }); const o2 = new ParseObject('Delivery'); @@ -106,7 +100,7 @@ describe('ParseRelation', () => { r.add([o2, o3]); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'AddRelation', @@ -114,7 +108,7 @@ describe('ParseRelation', () => { { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, - ] + ], }); }); @@ -128,25 +122,21 @@ describe('ParseRelation', () => { expect(p).toBeTruthy(); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'AddRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1234', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D1234', className: 'Delivery' }], }); // Adding empty array shouldn't change the relation r.add([]); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'AddRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1234', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D1234', className: 'Delivery' }], }); }); @@ -154,21 +144,21 @@ describe('ParseRelation', () => { const relation = new ParseRelation(); expect(() => { relation.add([]); - }).toThrow('Cannot add to a Relation without a parent') + }).toThrow('Cannot add to a Relation without a parent'); }); it('cannot remove from relation without parent', () => { const relation = new ParseRelation(); expect(() => { relation.remove([]); - }).toThrow('Cannot remove from a Relation without a parent') + }).toThrow('Cannot remove from a Relation without a parent'); }); it('cannot construct query from relation without parent', () => { const relation = new ParseRelation(); expect(() => { relation.query(); - }).toThrow('Cannot construct a query for a Relation without a parent') + }).toThrow('Cannot construct a query for a Relation without a parent'); }); it('can remove objects from a relation', () => { @@ -180,13 +170,11 @@ describe('ParseRelation', () => { r.remove(o); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'RemoveRelation', - objects: [ - { __type: 'Pointer', objectId: 'D1', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D1', className: 'Delivery' }], }); const o2 = new ParseObject('Delivery'); @@ -196,7 +184,7 @@ describe('ParseRelation', () => { r.remove([o2, o3]); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'RemoveRelation', @@ -204,7 +192,7 @@ describe('ParseRelation', () => { { __type: 'Pointer', objectId: 'D1', className: 'Delivery' }, { __type: 'Pointer', objectId: 'D2', className: 'Delivery' }, { __type: 'Pointer', objectId: 'D3', className: 'Delivery' }, - ] + ], }); }); @@ -217,25 +205,21 @@ describe('ParseRelation', () => { r.remove(o); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'RemoveRelation', - objects: [ - { __type: 'Pointer', objectId: 'D5678', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D5678', className: 'Delivery' }], }); // Removing empty array shouldn't change the relation r.remove([]); expect(r.toJSON()).toEqual({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); expect(parent.op('shipments').toJSON()).toEqual({ __op: 'RemoveRelation', - objects: [ - { __type: 'Pointer', objectId: 'D5678', className: 'Delivery' } - ] + objects: [{ __type: 'Pointer', objectId: 'D5678', className: 'Delivery' }], }); }); @@ -246,17 +230,17 @@ describe('ParseRelation', () => { let q = r.query(); expect(q.className).toBe('Item'); expect(q._extraOptions).toEqual({ - redirectClassNameForKey: 'shipments' + redirectClassNameForKey: 'shipments', }); expect(q.where).toEqual({ $relatedTo: { object: { __type: 'Pointer', objectId: 'I1', - className: 'Item' + className: 'Item', }, - key: 'shipments' - } + key: 'shipments', + }, }); r = new ParseRelation(parent, 'shipments'); @@ -270,10 +254,10 @@ describe('ParseRelation', () => { object: { __type: 'Pointer', className: 'Item', - objectId: 'I1' + objectId: 'I1', }, - key: 'shipments' - } + key: 'shipments', + }, }); }); @@ -281,13 +265,15 @@ describe('ParseRelation', () => { const parent = new ParseObject('Item'); parent.id = 'I3'; const r = new ParseRelation(parent, 'shipments'); - expect(r._ensureParentAndKey.bind(r, new ParseObject('Item'), 'shipments')) - .toThrow('Internal Error. Relation retrieved from two different Objects.'); + expect(r._ensureParentAndKey.bind(r, new ParseObject('Item'), 'shipments')).toThrow( + 'Internal Error. Relation retrieved from two different Objects.' + ); expect(() => { - r._ensureParentAndKey(new ParseObject('TestObject'), 'shipments') - }).toThrow('Internal Error. Relation retrieved from two different Objects.') - expect(r._ensureParentAndKey.bind(r, parent, 'partners')) - .toThrow('Internal Error. Relation retrieved from two different keys.'); + r._ensureParentAndKey(new ParseObject('TestObject'), 'shipments'); + }).toThrow('Internal Error. Relation retrieved from two different Objects.'); + expect(r._ensureParentAndKey.bind(r, parent, 'partners')).toThrow( + 'Internal Error. Relation retrieved from two different keys.' + ); expect(r._ensureParentAndKey.bind(r, parent, 'shipments')).not.toThrow(); const noParent = new ParseRelation(null, null); diff --git a/src/__tests__/ParseRole-test.js b/src/__tests__/ParseRole-test.js index 090a544fc..e2e7fa0ff 100644 --- a/src/__tests__/ParseRole-test.js +++ b/src/__tests__/ParseRole-test.js @@ -49,34 +49,42 @@ describe('ParseRole', () => { const acl = new ParseACL({ aUserId: { read: true, write: true } }); const role = new ParseRole('admin', acl); role.id = '101'; - expect(role.validate({ - name: 'author' - })).toEqual(new ParseError( - ParseError.OTHER_CAUSE, - 'A role\'s name can only be set before it has been saved.' - )); + expect( + role.validate({ + name: 'author', + }) + ).toEqual( + new ParseError( + ParseError.OTHER_CAUSE, + "A role's name can only be set before it has been saved." + ) + ); role.id = undefined; - expect(role.validate({ - name: 12 - })).toEqual(new ParseError( - ParseError.OTHER_CAUSE, - 'A role\'s name must be a String.' - )); + expect( + role.validate({ + name: 12, + }) + ).toEqual(new ParseError(ParseError.OTHER_CAUSE, "A role's name must be a String.")); - expect(role.validate({ - name: '$$$' - })).toEqual(new ParseError( - ParseError.OTHER_CAUSE, - 'A role\'s name can be only contain alphanumeric characters, _, ' + - '-, and spaces.' - )); + expect( + role.validate({ + name: '$$$', + }) + ).toEqual( + new ParseError( + ParseError.OTHER_CAUSE, + "A role's name can be only contain alphanumeric characters, _, " + '-, and spaces.' + ) + ); - expect(role.validate({ - name: 'admin' - })).toBe(false); + expect( + role.validate({ + name: 'admin', + }) + ).toBe(false); const result = role.validate({ - 'invalid#field': 'admin' + 'invalid#field': 'admin', }); expect(result.code).toBe(ParseError.INVALID_KEY_NAME); }); @@ -85,7 +93,7 @@ describe('ParseRole', () => { const role = ParseObject.fromJSON({ className: '_Role', objectId: '102', - name: 'admin' + name: 'admin', }); expect(role instanceof ParseObject).toBe(true); expect(role instanceof ParseRole).toBe(true); diff --git a/src/__tests__/ParseSchema-test.js b/src/__tests__/ParseSchema-test.js index 04d88aa80..f1ad11f9b 100644 --- a/src/__tests__/ParseSchema-test.js +++ b/src/__tests__/ParseSchema-test.js @@ -8,16 +8,16 @@ */ jest.autoMockOff(); -const mockObject = function(className, id) { +const mockObject = function (className, id) { this.className = className; this.id = id; this.attributes = {}; - this.toPointer = function() { + this.toPointer = function () { return { className: this.className, __type: 'Pointer', objectId: this.id, - } + }; }; }; jest.setMock('../ParseObject', mockObject); @@ -29,19 +29,19 @@ const CoreManager = require('../CoreManager'); const defaultController = CoreManager.getSchemaController(); describe('ParseSchema', () => { - it('can create schema', (done) => { + it('can create schema', done => { const schema = new ParseSchema('SchemaTest'); expect(schema.className).toEqual('SchemaTest'); done(); }); - it('can create schema with User Class', (done) => { + it('can create schema with User Class', done => { const schema = new ParseSchema('User'); expect(schema.className).toEqual('_User'); done(); }); - it('cannot use schema without class', (done) => { + it('cannot use schema without class', done => { try { const schema = new ParseSchema(); schema.assertClassName(); @@ -50,7 +50,7 @@ describe('ParseSchema', () => { } }); - it('can create schema fields', (done) => { + it('can create schema fields', done => { const schema = new ParseSchema('SchemaTest'); schema .addField('defaultFieldString') @@ -87,10 +87,22 @@ describe('ParseSchema', () => { const object = new ParseObject('TestObject', '1234'); const schema = new ParseSchema('SchemaTest'); schema - .addField('defaultFieldString', 'String', { required: true, defaultValue: 'hello' }) - .addDate('dateField', { required: true, defaultValue: '2000-01-01T00:00:00.000Z' }) - .addPointer('pointerField', 'TestObject', { required: true, defaultValue: object }) - .addPointer('pointerJSONField', 'TestObject', { required: true, defaultValue: object.toPointer() }); + .addField('defaultFieldString', 'String', { + required: true, + defaultValue: 'hello', + }) + .addDate('dateField', { + required: true, + defaultValue: '2000-01-01T00:00:00.000Z', + }) + .addPointer('pointerField', 'TestObject', { + required: true, + defaultValue: object, + }) + .addPointer('pointerJSONField', 'TestObject', { + required: true, + defaultValue: object.toPointer(), + }); expect(schema._fields.defaultFieldString.type).toEqual('String'); expect(schema._fields.defaultFieldString.required).toEqual(true); @@ -102,11 +114,14 @@ describe('ParseSchema', () => { expect(schema._fields.dateField).toEqual({ type: 'Date', required: true, - defaultValue: { __type: 'Date', iso: new Date('2000-01-01T00:00:00.000Z') } + defaultValue: { + __type: 'Date', + iso: new Date('2000-01-01T00:00:00.000Z'), + }, }); }); - it('can create schema indexes', (done) => { + it('can create schema indexes', done => { const schema = new ParseSchema('SchemaTest'); schema.addIndex('testIndex', { name: 1 }); @@ -114,7 +129,7 @@ describe('ParseSchema', () => { done(); }); - it('can set schema class level permissions', (done) => { + it('can set schema class level permissions', done => { const schema = new ParseSchema('SchemaTest'); expect(schema._clp).toBeUndefined(); schema.setCLP(undefined); @@ -129,14 +144,14 @@ describe('ParseSchema', () => { update: { requiresAuthentication: true }, delete: {}, addField: {}, - protectedFields: {} + protectedFields: {}, }; schema.setCLP(clp); expect(schema._clp).toEqual(clp); done(); }); - it('cannot add field with null name', (done) => { + it('cannot add field with null name', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addField(null, 'string'); @@ -145,7 +160,7 @@ describe('ParseSchema', () => { } }); - it('cannot add field with invalid type', (done) => { + it('cannot add field with invalid type', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addField('testField', 'unknown'); @@ -154,16 +169,16 @@ describe('ParseSchema', () => { } }); - it('cannot add index with null name', (done) => { + it('cannot add index with null name', done => { try { const schema = new ParseSchema('SchemaTest'); - schema.addIndex(null, {'name': 1}); + schema.addIndex(null, { name: 1 }); } catch (e) { done(); } }); - it('cannot add index with null index', (done) => { + it('cannot add index with null index', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addIndex('testIndex', null); @@ -172,7 +187,7 @@ describe('ParseSchema', () => { } }); - it('cannot add pointer with null name', (done) => { + it('cannot add pointer with null name', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addPointer(null, 'targetClass'); @@ -181,7 +196,7 @@ describe('ParseSchema', () => { } }); - it('cannot add pointer with null targetClass', (done) => { + it('cannot add pointer with null targetClass', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addPointer('pointerField', null); @@ -190,7 +205,7 @@ describe('ParseSchema', () => { } }); - it('cannot add relation with null name', (done) => { + it('cannot add relation with null name', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addRelation(null, 'targetClass'); @@ -199,7 +214,7 @@ describe('ParseSchema', () => { } }); - it('cannot add relation with null targetClass', (done) => { + it('cannot add relation with null targetClass', done => { try { const schema = new ParseSchema('SchemaTest'); schema.addRelation('relationField', null); @@ -208,21 +223,21 @@ describe('ParseSchema', () => { } }); - it('can delete schema field', (done) => { + it('can delete schema field', done => { const schema = new ParseSchema('SchemaTest'); schema.deleteField('testField'); - expect(schema._fields.testField).toEqual({ __op: 'Delete'}); + expect(schema._fields.testField).toEqual({ __op: 'Delete' }); done(); }); - it('can delete schema index', (done) => { + it('can delete schema index', done => { const schema = new ParseSchema('SchemaTest'); schema.deleteIndex('testIndex'); - expect(schema._indexes.testIndex).toEqual({ __op: 'Delete'}); + expect(schema._indexes.testIndex).toEqual({ __op: 'Delete' }); done(); }); - it('can save schema', (done) => { + it('can save schema', done => { CoreManager.setSchemaController({ send() {}, get() {}, @@ -233,8 +248,8 @@ describe('ParseSchema', () => { expect(className).toBe('SchemaTest'); expect(params).toEqual({ className: 'SchemaTest', - fields: { name: { type: 'String'} }, - indexes: { testIndex: { name: 1 } } + fields: { name: { type: 'String' } }, + indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, @@ -242,14 +257,14 @@ describe('ParseSchema', () => { const schema = new ParseSchema('SchemaTest'); schema.addField('name'); - schema.addIndex('testIndex', {'name': 1}); - schema.save().then((results) => { + schema.addIndex('testIndex', { name: 1 }); + schema.save().then(results => { expect(results).toEqual([]); done(); }); }); - it('can update schema', (done) => { + it('can update schema', done => { CoreManager.setSchemaController({ send() {}, get() {}, @@ -260,8 +275,8 @@ describe('ParseSchema', () => { expect(className).toBe('SchemaTest'); expect(params).toEqual({ className: 'SchemaTest', - fields: { name: { type: 'String'} }, - indexes: { testIndex: { name: 1 } } + fields: { name: { type: 'String' } }, + indexes: { testIndex: { name: 1 } }, }); return Promise.resolve([]); }, @@ -269,14 +284,14 @@ describe('ParseSchema', () => { const schema = new ParseSchema('SchemaTest'); schema.addField('name'); - schema.addIndex('testIndex', {'name': 1}); - schema.update().then((results) => { + schema.addIndex('testIndex', { name: 1 }); + schema.update().then(results => { expect(results).toEqual([]); done(); }); }); - it('can delete schema', (done) => { + it('can delete schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -290,13 +305,13 @@ describe('ParseSchema', () => { }); const schema = new ParseSchema('SchemaTest'); - schema.delete().then((results) => { + schema.delete().then(results => { expect(results).toEqual([]); done(); }); }); - it('can purge schema', (done) => { + it('can purge schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -310,13 +325,13 @@ describe('ParseSchema', () => { }); const schema = new ParseSchema('SchemaTest'); - schema.purge().then((results) => { + schema.purge().then(results => { expect(results).toEqual([]); done(); }); }); - it('can get schema', (done) => { + it('can get schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -330,13 +345,13 @@ describe('ParseSchema', () => { }); const schema = new ParseSchema('SchemaTest'); - schema.get().then((results) => { + schema.get().then(results => { expect(results).toEqual([]); done(); }); }); - it('cannot get empty schema', (done) => { + it('cannot get empty schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -350,17 +365,20 @@ describe('ParseSchema', () => { }); const schema = new ParseSchema('SchemaTest'); - schema.get().then(() => { - // Should never reach - expect(true).toBe(false); - done(); - }, (error) => { - expect(error.message).toBe('Schema not found.'); - done(); - }); + schema.get().then( + () => { + // Should never reach + expect(true).toBe(false); + done(); + }, + error => { + expect(error.message).toBe('Schema not found.'); + done(); + } + ); }); - it('can get all schema', (done) => { + it('can get all schema', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -370,18 +388,18 @@ describe('ParseSchema', () => { get(className) { expect(className).toBe(''); return Promise.resolve({ - results: ['all'] + results: ['all'], }); }, }); - ParseSchema.all().then((results) => { + ParseSchema.all().then(results => { expect(results[0]).toEqual('all'); done(); }); }); - it('cannot get all schema when empty', (done) => { + it('cannot get all schema when empty', done => { CoreManager.setSchemaController({ send() {}, create() {}, @@ -391,69 +409,72 @@ describe('ParseSchema', () => { get(className) { expect(className).toBe(''); return Promise.resolve({ - results: [] + results: [], }); }, }); - ParseSchema.all().then(() => { - // Should never reach - expect(true).toBe(false); - done(); - }, (error) => { - expect(error.message).toBe('Schema not found.'); - done(); - }); + ParseSchema.all().then( + () => { + // Should never reach + expect(true).toBe(false); + done(); + }, + error => { + expect(error.message).toBe('Schema not found.'); + done(); + } + ); }); }); describe('SchemaController', () => { beforeEach(() => { CoreManager.setSchemaController(defaultController); - const request = function() { + const request = function () { return Promise.resolve([]); }; - const ajax = function() { + const ajax = function () { return Promise.resolve([]); }; CoreManager.setRESTController({ request: request, ajax: ajax }); }); - it('save schema', (done) => { + it('save schema', done => { const schema = new ParseSchema('SchemaTest'); - schema.save().then((results) => { + schema.save().then(results => { expect(results).toEqual([]); done(); }); }); - it('get schema', (done) => { + it('get schema', done => { const schema = new ParseSchema('SchemaTest'); - schema.get().then((results) => { + schema.get().then(results => { expect(results).toEqual([]); done(); }); }); - it('update schema', (done) => { + it('update schema', done => { const schema = new ParseSchema('SchemaTest'); - schema.update().then((results) => { + schema.update().then(results => { expect(results).toEqual([]); done(); }); }); - it('delete schema', (done) => { + it('delete schema', done => { const schema = new ParseSchema('SchemaTest'); - schema.delete().then((results) => { + schema.delete().then(results => { expect(results).toEqual([]); done(); }); }); - it('purge schema', (done) => { + it('purge schema', done => { const schema = new ParseSchema('SchemaTest'); - schema.purge().then((results) => { + schema.purge().then(results => { expect(results).toEqual([]); done(); }); diff --git a/src/__tests__/ParseSession-test.js b/src/__tests__/ParseSession-test.js index 0f278350d..9a9766499 100644 --- a/src/__tests__/ParseSession-test.js +++ b/src/__tests__/ParseSession-test.js @@ -11,7 +11,7 @@ jest.dontMock('../CoreManager'); jest.dontMock('../decode'); jest.dontMock('../encode'); jest.dontMock('../isRevocableSession'); -jest.dontMock('../ObjectStateMutations') +jest.dontMock('../ObjectStateMutations'); jest.dontMock('../parseDate'); jest.dontMock('../ParseError'); jest.dontMock('../ParseObject'); @@ -26,13 +26,13 @@ jest.dontMock('../UniqueInstanceStateController'); jest.dontMock('./test_helpers/mockXHR'); -const mockUser = function(token) { +const mockUser = function (token) { this.token = token; }; -mockUser.prototype.getSessionToken = function() { +mockUser.prototype.getSessionToken = function () { return this.token; }; -mockUser.current = function() { +mockUser.current = function () { return null; }; jest.setMock('../ParseUser', mockUser); @@ -52,14 +52,14 @@ describe('ParseSession', () => { expect(session.get('someField')).toBe('someValue'); session = new ParseSession({ - someField: 'someValue' + someField: 'someValue', }); expect(session.get('someField')).toBe('someValue'); }); it('cannot create schema with invalid fields', () => { expect(() => { - new ParseSession({ 'invalid#name' : 'foo'}) + new ParseSession({ 'invalid#name': 'foo' }); }).toThrow("Can't create an invalid Session"); }); @@ -89,22 +89,28 @@ describe('ParseSession', () => { const session = new ParseSession(); session._finishFetch({ id: 'session1', - sessionToken: 'abc123' + sessionToken: 'abc123', }); expect(session.getSessionToken()).toBe('abc123'); }); it('checks the current user for a revocable token', () => { expect(ParseSession.isCurrentSessionRevocable()).toBe(false); - mockUser.current = function() { return new mockUser('r:abc123'); }; + mockUser.current = function () { + return new mockUser('r:abc123'); + }; expect(ParseSession.isCurrentSessionRevocable()).toBe(true); - mockUser.current = function() { return new mockUser('abc123'); }; + mockUser.current = function () { + return new mockUser('abc123'); + }; expect(ParseSession.isCurrentSessionRevocable()).toBe(false); - mockUser.current = function() { return new mockUser(null); }; + mockUser.current = function () { + return new mockUser(null); + }; expect(ParseSession.isCurrentSessionRevocable()).toBe(false); }); - it('can fetch the full session for the current token', (done) => { + it('can fetch the full session for the current token', done => { CoreManager.setRESTController({ request(method, path, body, options) { expect(method).toBe('GET'); @@ -115,16 +121,16 @@ describe('ParseSession', () => { }); return Promise.resolve({ objectId: 'session1', - sessionToken: 'abc123' + sessionToken: 'abc123', }); }, - ajax() {} + ajax() {}, }); - mockUser.currentAsync = function() { + mockUser.currentAsync = function () { return Promise.resolve(new mockUser('abc123')); }; - ParseSession.current({ useMasterKey: true }).then((session) => { + ParseSession.current({ useMasterKey: true }).then(session => { expect(session instanceof ParseSession).toBe(true); expect(session.id).toBe('session1'); expect(session.getSessionToken()).toBe('abc123'); @@ -132,12 +138,12 @@ describe('ParseSession', () => { }); }); - it('cannot get current session without current user', (done) => { - mockUser.currentAsync = function() { + it('cannot get current session without current user', done => { + mockUser.currentAsync = function () { return Promise.resolve(null); }; - ParseSession.current().catch((error) => { - expect(error).toBe('There is no current user.') + ParseSession.current().catch(error => { + expect(error).toBe('There is no current user.'); done(); }); }); @@ -146,7 +152,7 @@ describe('ParseSession', () => { const s = ParseObject.fromJSON({ className: '_Session', sessionToken: '123abc', - foo: 12 + foo: 12, }); const clone = s.clone(); diff --git a/src/__tests__/ParseUser-test.js b/src/__tests__/ParseUser-test.js index fce28b737..e081ecba7 100644 --- a/src/__tests__/ParseUser-test.js +++ b/src/__tests__/ParseUser-test.js @@ -70,16 +70,16 @@ describe('ParseUser', () => { u = new ParseUser({ username: 'andrew', - password: 'secret' + password: 'secret', }); expect(u.get('username')).toBe('andrew'); expect(u.get('password')).toBe('secret'); - expect(function() { + expect(function () { new ParseUser({ - $$$: 'invalid' + $$$: 'invalid', }); - }).toThrow('Can\'t create an invalid Parse User'); + }).toThrow("Can't create an invalid Parse User"); }); it('exposes certain attributes through special setters and getters', () => { @@ -87,7 +87,7 @@ describe('ParseUser', () => { className: '_User', username: 'user12', email: 'user12@parse.com', - sessionToken: '123abc' + sessionToken: '123abc', }); expect(u instanceof ParseUser).toBe(true); expect(u.getUsername()).toBe('user12'); @@ -119,7 +119,7 @@ describe('ParseUser', () => { className: '_User', username: 'user12', email: 'user12@parse.com', - sessionToken: '123abc' + sessionToken: '123abc', }); const clone = u.clone(); @@ -136,7 +136,7 @@ describe('ParseUser', () => { objectId: 'U111', username: 'u111', email: 'u111@parse.com', - sesionToken: '1313' + sesionToken: '1313', }); let o2 = o.newInstance(); expect(o.id).toBe(o2.id); @@ -164,7 +164,7 @@ describe('ParseUser', () => { ); }); - it('can sign up a new user', (done) => { + it('can sign up a new user', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -174,25 +174,34 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid', - }, 201); + return Promise.resolve( + { + objectId: 'uid', + }, + 201 + ); }, - ajax() {} - }); - ParseUser.signUp(null, 'password').then(() => { - // Should not be reached - expect(true).toBe(false); - }, (error) => { - expect(error.message).toBe('Cannot sign up user with an empty username.'); - }); - ParseUser.signUp('username').then(() => { - // Should not be reached - expect(true).toBe(false); - }, (error) => { - expect(error.message).toBe('Cannot sign up user with an empty password.'); + ajax() {}, }); - ParseUser.signUp('username', 'password').then((u) => { + ParseUser.signUp(null, 'password').then( + () => { + // Should not be reached + expect(true).toBe(false); + }, + error => { + expect(error.message).toBe('Cannot sign up user with an empty username.'); + } + ); + ParseUser.signUp('username').then( + () => { + // Should not be reached + expect(true).toBe(false); + }, + error => { + expect(error.message).toBe('Cannot sign up user with an empty password.'); + } + ); + ParseUser.signUp('username', 'password').then(u => { expect(u.id).toBe('uid'); expect(u.get('username')).toBe('username'); expect(u.get('password')).toBe(undefined); @@ -209,7 +218,7 @@ describe('ParseUser', () => { }); }); - it('can log in as a user', (done) => { + it('can log in as a user', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -219,15 +228,18 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password').then((u) => { + ParseUser.logIn('username', 'password').then(u => { expect(u.id).toBe('uid2'); expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); @@ -252,14 +264,17 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); expect(options.useMasterKey).toBe(true); - expect(options.installationId).toBe('installation1234') - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + expect(options.installationId).toBe('installation1234'); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.logIn('username', 'password', { useMasterKey: true, @@ -268,7 +283,7 @@ describe('ParseUser', () => { expect(user.id).toBe('uid2'); }); - it('can log in as a user with POST method', (done) => { + it('can log in as a user with POST method', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -278,15 +293,18 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password', { usePost: true }).then((u) => { + ParseUser.logIn('username', 'password', { usePost: true }).then(u => { expect(u.id).toBe('uid2'); expect(u.getSessionToken()).toBe('123abc'); expect(u.isCurrent()).toBe(true); @@ -301,23 +319,25 @@ describe('ParseUser', () => { }); }); - it('fail login when invalid username or password is used', (done) => { + it('fail login when invalid username or password is used', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); - ParseUser.logIn({}, 'password').then(null, (err) => { - expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe('Username must be a string.'); - - return ParseUser.logIn('username', {}); - }).then(null, (err) => { - expect(err.code).toBe(ParseError.OTHER_CAUSE); - expect(err.message).toBe('Password must be a string.'); - - done(); - }); + ParseUser.logIn({}, 'password') + .then(null, err => { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('Username must be a string.'); + + return ParseUser.logIn('username', {}); + }) + .then(null, err => { + expect(err.code).toBe(ParseError.OTHER_CAUSE); + expect(err.message).toBe('Password must be a string.'); + + done(); + }); }); - it('preserves changes when logging in', (done) => { + it('preserves changes when logging in', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -327,17 +347,20 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const u = new ParseUser({ username: 'username', - password: 'password' + password: 'password', }); u.set('count', 5); u.logIn().then(() => { @@ -348,7 +371,7 @@ describe('ParseUser', () => { }); }); - it('can become a user with a session token', (done) => { + it('can become a user with a session token', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ @@ -357,16 +380,19 @@ describe('ParseUser', () => { expect(path).toBe('users/me'); expect(options.sessionToken).toBe('123abc'); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.become('123abc').then((u) => { + ParseUser.become('123abc').then(u => { expect(u.id).toBe('uid3'); expect(u.isCurrent()).toBe(true); expect(u.existed()).toBe(true); @@ -385,13 +411,16 @@ describe('ParseUser', () => { expect(path).toBe('users/me'); expect(options.sessionToken).toBe('123abc'); expect(options.useMasterKey).toBe(true); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const u = await ParseUser.become('123abc', { useMasterKey: true }); @@ -408,12 +437,13 @@ describe('ParseUser', () => { ParseUser._clearCache(); expect(() => { ParseUser.current(); - }).toThrow('Cannot call currentUser() when using a platform with an async storage system. Call currentUserAsync() instead.'); + }).toThrow( + 'Cannot call currentUser() when using a platform with an async storage system. Call currentUserAsync() instead.' + ); CoreManager.setStorageController(StorageController); }); - it('can hydrate a user with sessionToken in server environment', async () => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); @@ -462,7 +492,7 @@ describe('ParseUser', () => { return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); ParseUser.requestPasswordReset('me@parse.com'); @@ -475,122 +505,142 @@ describe('ParseUser', () => { expect(options.useMasterKey).toBe(true); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); ParseUser.requestPasswordReset('me@parse.com', { useMasterKey: true }); }); - it('can log out a user', (done) => { + it('can log out a user', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid5', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid5', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password').then((u) => { - expect(ParseUser.current()).toBe(u); - CoreManager.setRESTController({ - request() { - // Shouldn't be called - expect(true).toBe(false); - return Promise.resolve({}, 200); - }, - ajax() {} + ParseUser.logIn('username', 'password') + .then(u => { + expect(ParseUser.current()).toBe(u); + CoreManager.setRESTController({ + request() { + // Shouldn't be called + expect(true).toBe(false); + return Promise.resolve({}, 200); + }, + ajax() {}, + }); + return ParseUser.logOut(); + }) + .then(() => { + expect(ParseUser.current()).toBe(null); + done(); }); - return ParseUser.logOut(); - }).then(() => { - expect(ParseUser.current()).toBe(null); - done(); - }); }); - it('can revoke a session on logout', (done) => { + it('can revoke a session on logout', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - username: 'username', - sessionToken: 'r:123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + username: 'username', + sessionToken: 'r:123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.logIn('username', 'password').then((u) => { - expect(ParseUser.current()).toBe(u); - CoreManager.setRESTController({ - request(method, path, body, options) { - expect(method).toBe('POST'); - expect(path).toBe('logout'); - expect(options).toEqual({ - sessionToken: 'r:123abc' - }); - return Promise.resolve({}, 200); - }, - ajax() {} + ParseUser.logIn('username', 'password') + .then(u => { + expect(ParseUser.current()).toBe(u); + CoreManager.setRESTController({ + request(method, path, body, options) { + expect(method).toBe('POST'); + expect(path).toBe('logout'); + expect(options).toEqual({ + sessionToken: 'r:123abc', + }); + return Promise.resolve({}, 200); + }, + ajax() {}, + }); + return ParseUser.logOut(); + }) + .then(() => { + expect(ParseUser.current()).toBe(null); + done(); }); - return ParseUser.logOut(); - }).then(() => { - expect(ParseUser.current()).toBe(null); - done(); - }); }); - it('can get the current user asynchronously', (done) => { + it('can get the current user asynchronously', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - username: 'username', - sessionToken: 'r:123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + username: 'username', + sessionToken: 'r:123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.currentAsync().then((u) => { - expect(u).toBe(null); - return ParseUser.logIn('username', 'password'); - }).then((u) => { - expect(u instanceof ParseUser).toBe(true); - return ParseUser.currentAsync(); - }).then((u) => { - expect(u instanceof ParseUser).toBe(true); - expect(u.getUsername()).toBe('username'); - expect(u.id).toBe('uid6'); - - ParseUser.disableUnsafeCurrentUser(); - return ParseUser.currentAsync(); - }).then((u) => { - expect(u).toBe(null); - done(); - }); + ParseUser.currentAsync() + .then(u => { + expect(u).toBe(null); + return ParseUser.logIn('username', 'password'); + }) + .then(u => { + expect(u instanceof ParseUser).toBe(true); + return ParseUser.currentAsync(); + }) + .then(u => { + expect(u instanceof ParseUser).toBe(true); + expect(u.getUsername()).toBe('username'); + expect(u.id).toBe('uid6'); + + ParseUser.disableUnsafeCurrentUser(); + return ParseUser.currentAsync(); + }) + .then(u => { + expect(u).toBe(null); + done(); + }); }); - it('can inflate users stored from previous SDK versions', (done) => { + it('can inflate users stored from previous SDK versions', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); const path = Storage.generatePath('currentUser'); - Storage.setItem(path, JSON.stringify({ - _id: 'abc', - _sessionToken: '12345', - objectId: 'abc', - username: 'bob', - count: 12 - })); - ParseUser.currentAsync().then((u) => { + Storage.setItem( + path, + JSON.stringify({ + _id: 'abc', + _sessionToken: '12345', + objectId: 'abc', + username: 'bob', + count: 12, + }) + ); + ParseUser.currentAsync().then(u => { expect(u instanceof ParseUser).toBe(true); expect(u.getUsername()).toBe('bob'); expect(u.id).toBe('abc'); @@ -606,19 +656,22 @@ describe('ParseUser', () => { }); }); - it('can inflate users stored from previous SDK versions override _id', (done) => { + it('can inflate users stored from previous SDK versions override _id', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); const path = Storage.generatePath('currentUser'); - Storage.setItem(path, JSON.stringify({ - _id: 'abc', - _sessionToken: '12345', - objectId: 'SET', - username: 'bob', - count: 12 - })); - ParseUser.currentAsync().then((u) => { + Storage.setItem( + path, + JSON.stringify({ + _id: 'abc', + _sessionToken: '12345', + objectId: 'SET', + username: 'bob', + count: 12, + }) + ); + ParseUser.currentAsync().then(u => { expect(u instanceof ParseUser).toBe(true); expect(u.getUsername()).toBe('bob'); expect(u.id).toBe('abc'); @@ -634,109 +687,130 @@ describe('ParseUser', () => { }); }); - it('updates the current user on disk when saved', (done) => { + it('updates the current user on disk when saved', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid5', - }, 201); + return Promise.resolve( + { + objectId: 'uid5', + }, + 201 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.signUp('updater', 'password').then((u) => { - expect(u.isCurrent()).toBe(true); - ParseUser._clearCache(); - CoreManager.setRESTController({ - request() { - return Promise.resolve({}, 200); - }, - ajax() {} + ParseUser.signUp('updater', 'password') + .then(u => { + expect(u.isCurrent()).toBe(true); + ParseUser._clearCache(); + CoreManager.setRESTController({ + request() { + return Promise.resolve({}, 200); + }, + ajax() {}, + }); + return u.save({ count: 12 }); + }) + .then(u => { + ParseUser._clearCache(); + ParseObject._clearAllState(); + expect(u.attributes).toEqual({}); + expect(u.get('count')).toBe(undefined); + return ParseUser.currentAsync(); + }) + .then(current => { + expect(current.id).toBe('uid5'); + expect(current.get('count')).toBe(12); + done(); }); - return u.save({ count: 12 }); - }).then((u) => { - ParseUser._clearCache(); - ParseObject._clearAllState(); - expect(u.attributes).toEqual({}); - expect(u.get('count')).toBe(undefined); - return ParseUser.currentAsync(); - }).then((current) => { - expect(current.id).toBe('uid5'); - expect(current.get('count')).toBe(12); - done(); - }); }); - it('removes the current user from disk when destroyed', (done) => { + it('removes the current user from disk when destroyed', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid9', - }, 201); + return Promise.resolve( + { + objectId: 'uid9', + }, + 201 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.signUp('destroyed', 'password').then((u) => { - expect(u.isCurrent()).toBe(true); - CoreManager.setRESTController({ - request() { - return Promise.resolve({}, 200); - }, - ajax() {} + ParseUser.signUp('destroyed', 'password') + .then(u => { + expect(u.isCurrent()).toBe(true); + CoreManager.setRESTController({ + request() { + return Promise.resolve({}, 200); + }, + ajax() {}, + }); + return u.destroy(); + }) + .then(() => { + expect(ParseUser.current()).toBe(null); + return ParseUser.currentAsync(); + }) + .then(current => { + expect(current).toBe(null); + done(); }); - return u.destroy(); - }).then(() => { - expect(ParseUser.current()).toBe(null); - return ParseUser.currentAsync(); - }).then((current) => { - expect(current).toBe(null); - done(); - }); }); - it('updates the current user on disk when fetched', (done) => { + it('updates the current user on disk when fetched', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6' - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.signUp('spot', 'fetch').then((u) => { - expect(u.isCurrent()).toBe(true); - ParseUser._clearCache(); - CoreManager.setRESTController({ - request() { - return Promise.resolve({ - count: 15 - }, 200); - }, - ajax() {} + ParseUser.signUp('spot', 'fetch') + .then(u => { + expect(u.isCurrent()).toBe(true); + ParseUser._clearCache(); + CoreManager.setRESTController({ + request() { + return Promise.resolve( + { + count: 15, + }, + 200 + ); + }, + ajax() {}, + }); + return u.fetch(); + }) + .then(u => { + ParseUser._clearCache(); + ParseObject._clearAllState(); + expect(u.attributes).toEqual({}); + expect(u.get('count')).toBe(undefined); + return ParseUser.currentAsync(); + }) + .then(current => { + expect(current.id).toBe('uid6'); + expect(current.get('count')).toBe(15); + done(); }); - return u.fetch(); - }).then((u) => { - ParseUser._clearCache(); - ParseObject._clearAllState(); - expect(u.attributes).toEqual({}); - expect(u.get('count')).toBe(undefined); - return ParseUser.currentAsync(); - }).then((current) => { - expect(current.id).toBe('uid6'); - expect(current.get('count')).toBe(15); - done(); - }); }); it('updates the current user on disk when fetched with include', async () => { @@ -745,9 +819,12 @@ describe('ParseUser', () => { Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + }, + 200 + ); }, ajax() {}, }); @@ -760,10 +837,13 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - child: child.toJSON(), - count: 15, - }, 200); + return Promise.resolve( + { + child: child.toJSON(), + count: 15, + }, + 200 + ); }, ajax() {}, }); @@ -785,9 +865,12 @@ describe('ParseUser', () => { Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + }, + 200 + ); }, ajax() {}, }); @@ -801,10 +884,13 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - child: child.toJSON(), - count: 15, - }, 200); + return Promise.resolve( + { + child: child.toJSON(), + count: 15, + }, + 200 + ); }, ajax() {}, }); @@ -816,37 +902,42 @@ describe('ParseUser', () => { expect(fetchedUser.get('child').foo).toBe('bar'); }); - it('clears the current user on disk when logged out', (done) => { + it('clears the current user on disk when logged out', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid5', - }, 201); + return Promise.resolve( + { + objectId: 'uid5', + }, + 201 + ); }, - ajax() {} + ajax() {}, }); const path = Storage.generatePath('currentUser'); - ParseUser.signUp('temporary', 'password').then((u) => { - expect(u.isCurrent()).toBe(true); - expect(Storage.getItem(path)).not.toBe(null); - ParseUser._clearCache(); - CoreManager.setRESTController({ - request() { - return Promise.resolve({}, 200); - }, - ajax() {} + ParseUser.signUp('temporary', 'password') + .then(u => { + expect(u.isCurrent()).toBe(true); + expect(Storage.getItem(path)).not.toBe(null); + ParseUser._clearCache(); + CoreManager.setRESTController({ + request() { + return Promise.resolve({}, 200); + }, + ajax() {}, + }); + return ParseUser.logOut(); + }) + .then(() => { + ParseUser._clearCache(); + expect(ParseUser.current()).toBe(null); + expect(Storage.getItem(path)).toBe(null); + done(); }); - return ParseUser.logOut(); - }).then(() => { - ParseUser._clearCache(); - expect(ParseUser.current()).toBe(null); - expect(Storage.getItem(path)).toBe(null); - done(); - }); }); it('can retreive a user with sessionToken (me)', async () => { @@ -857,13 +948,16 @@ describe('ParseUser', () => { expect(method).toBe('GET'); expect(path).toBe('users/me'); expect(options.sessionToken).toBe('123abc'); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.me('123abc'); @@ -881,13 +975,16 @@ describe('ParseUser', () => { expect(path).toBe('users/me'); expect(options.sessionToken).toBe('123abc'); expect(options.useMasterKey).toBe(true); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.me('123abc', { useMasterKey: true }); @@ -904,24 +1001,29 @@ describe('ParseUser', () => { request() { return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }; jest.spyOn(RESTController, 'request'); CoreManager.setRESTController(RESTController); await ParseUser.logOut({ sessionToken: '1234' }); - expect(RESTController.request).toHaveBeenCalledWith('POST', 'logout', {}, { sessionToken: '1234' }); + expect(RESTController.request).toHaveBeenCalledWith( + 'POST', + 'logout', + {}, + { sessionToken: '1234' } + ); }); - it('can get error when recursive _linkWith call fails', (done) => { + it('can get error when recursive _linkWith call fails', done => { CoreManager.setRESTController({ request(method, path, body) { expect(method).toBe('POST'); expect(path).toBe('users'); expect(body.authData.test).toEqual({ - id : 'id', - access_token : 'access_token' + id: 'id', + access_token: 'access_token', }); const error = new ParseError( ParseError.ACCOUNT_ALREADY_LINKED, @@ -929,14 +1031,14 @@ describe('ParseUser', () => { ); return Promise.reject(error); }, - ajax() {} + ajax() {}, }); const provider = { authenticate(options) { if (options.success) { options.success(this, { id: 'id', - access_token: 'access_token' + access_token: 'access_token', }); } }, @@ -947,16 +1049,19 @@ describe('ParseUser', () => { return 'test'; }, - deauthenticate() {} + deauthenticate() {}, }; - ParseUser.logInWith(provider, {}).then(() => { - // Should not run - }, (error) => { - expect(error.code).toBe(ParseError.ACCOUNT_ALREADY_LINKED); - expect(error.message).toBe('Another user is already linked to this facebook id.'); - done(); - }); + ParseUser.logInWith(provider, {}).then( + () => { + // Should not run + }, + error => { + expect(error.code).toBe(ParseError.ACCOUNT_ALREADY_LINKED); + expect(error.message).toBe('Another user is already linked to this facebook id.'); + done(); + } + ); }); it('can sync anonymous user with current user', async () => { @@ -966,10 +1071,10 @@ describe('ParseUser', () => { const object = new ParseUser(); object.set('authData', provider.getAuthData()); - jest.spyOn(object, 'isCurrent') - .mockImplementationOnce(() => true); + jest.spyOn(object, 'isCurrent').mockImplementationOnce(() => true); - const spy = jest.spyOn(ParseUser, 'currentAsync') + const spy = jest + .spyOn(ParseUser, 'currentAsync') .mockImplementationOnce(() => Promise.resolve(object)); ParseUser._registerAuthenticationProvider(provider); @@ -986,17 +1091,20 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid5', - sessionToken: 'r:123abc', - authData: { - anonymous: { - id: 'anonymousId', - } - } - }, 200); + return Promise.resolve( + { + objectId: 'uid5', + sessionToken: 'r:123abc', + authData: { + anonymous: { + id: 'anonymousId', + }, + }, + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await AnonymousUtils.logIn(); jest.spyOn(user, 'destroy'); @@ -1020,13 +1128,12 @@ describe('ParseUser', () => { const provider = AnonymousUtils._getAuthProvider(); ParseUser._registerAuthenticationProvider(provider); const user = new ParseUser(); - jest.spyOn(user, 'linkWith') - .mockImplementationOnce((authProvider, authData, saveOptions) => { - expect(authProvider).toEqual(provider.getAuthType()); - expect(authData).toEqual({ authData: null}); - expect(saveOptions).toEqual({ useMasterKey: true }); - return Promise.resolve(); - }); + jest.spyOn(user, 'linkWith').mockImplementationOnce((authProvider, authData, saveOptions) => { + expect(authProvider).toEqual(provider.getAuthType()); + expect(authData).toEqual({ authData: null }); + expect(saveOptions).toEqual({ useMasterKey: true }); + return Promise.resolve(); + }); user._unlinkFrom(provider.getAuthType(), { useMasterKey: true }); expect(user.linkWith).toHaveBeenCalledTimes(1); }); @@ -1036,17 +1143,20 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid5', - sessionToken: 'r:123abc', - authData: { - anonymous: { - id: 'anonymousId', - } - } - }, 200); + return Promise.resolve( + { + objectId: 'uid5', + sessionToken: 'r:123abc', + authData: { + anonymous: { + id: 'anonymousId', + }, + }, + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await AnonymousUtils.logIn(); jest.spyOn(user, 'destroy'); @@ -1054,25 +1164,28 @@ describe('ParseUser', () => { CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - await ParseUser.logIn('username', 'password') + await ParseUser.logIn('username', 'password'); expect(user.destroy).toHaveBeenCalledTimes(1); }); it('strip anonymity when we set username', () => { const user = new ParseUser(); const authData = { - anonymous : { - id : 'anonymousId' - } - } + anonymous: { + id: 'anonymousId', + }, + }; user.set('authData', authData); expect(user.get('authData').anonymous.id).toBe('anonymousId'); @@ -1082,32 +1195,38 @@ describe('ParseUser', () => { expect(user.get('authData').anonymous).toBe(null); }); - it('maintains the session token when refetched', (done) => { + it('maintains the session token when refetched', done => { ParseUser.enableUnsafeCurrentUser(); ParseUser._clearCache(); Storage._clear(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uidfetch', - username: 'temporary', - number: 123, - sessionToken: 'abc141', - }, 201); + return Promise.resolve( + { + objectId: 'uidfetch', + username: 'temporary', + number: 123, + sessionToken: 'abc141', + }, + 201 + ); }, - ajax() {} + ajax() {}, }); - ParseUser.signUp('temporary', 'password').then((u) => { + ParseUser.signUp('temporary', 'password').then(u => { expect(u.getSessionToken()).toBe('abc141'); expect(u.get('number')).toBe(123); ParseUser._clearCache(); - const u2 = ParseObject.fromJSON({ - objectId: 'uidfetch', - className: '_User', - username: 'temporary', - }, true); + const u2 = ParseObject.fromJSON( + { + objectId: 'uidfetch', + className: '_User', + username: 'temporary', + }, + true + ); expect(u.getSessionToken()).toBe('abc141'); expect(u2.getSessionToken()).toBe('abc141'); expect(u.get('number')).toBe(undefined); @@ -1121,25 +1240,28 @@ describe('ParseUser', () => { CoreManager.setRESTController({ request(method, path, body, options) { expect(options).toEqual(expect.objectContaining({ useMasterKey: true })); - return Promise.resolve({ - objectId: 'uid5', - sessionToken: 'r:123abc', - authData: { - test: { - id: 'id', - access_token: 'access_token' - } - } - }, 200); + return Promise.resolve( + { + objectId: 'uid5', + sessionToken: 'r:123abc', + authData: { + test: { + id: 'id', + access_token: 'access_token', + }, + }, + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const provider = { authenticate(options) { if (options.success) { options.success(this, { id: 'id', - access_token: 'access_token' + access_token: 'access_token', }); } }, @@ -1147,13 +1269,15 @@ describe('ParseUser', () => { getAuthType() { return 'test'; }, - deauthenticate() {} + deauthenticate() {}, }; const user = new ParseUser(); await user._linkWith(provider, null, { useMasterKey: true }); - expect(user.get('authData')).toEqual({ test: { id: 'id', access_token: 'access_token' } }); + expect(user.get('authData')).toEqual({ + test: { id: 'id', access_token: 'access_token' }, + }); }); it('handle linkWith authentication failure', async () => { @@ -1169,7 +1293,7 @@ describe('ParseUser', () => { getAuthType() { return 'test'; }, - deauthenticate() {} + deauthenticate() {}, }; const user = new ParseUser(); @@ -1177,7 +1301,7 @@ describe('ParseUser', () => { await user.linkWith(provider, null); expect(false).toBe(true); } catch (e) { - expect(e.message).toBe('authentication failed') + expect(e.message).toBe('authentication failed'); } }); @@ -1185,17 +1309,20 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid6', - sessionToken: 'r:123abc', - authData: { - testProvider: { - id: 'test', - } - } - }, 200); + return Promise.resolve( + { + objectId: 'uid6', + sessionToken: 'r:123abc', + authData: { + testProvider: { + id: 'test', + }, + }, + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = new ParseUser(); await user._linkWith('testProvider', { authData: { id: 'test' } }); @@ -1249,7 +1376,7 @@ describe('ParseUser', () => { getAuthType: () => 'customAuth', }; - user.set('authData', { 'customAuth': true }); + user.set('authData', { customAuth: true }); expect(user._isLinked(provider)).toBe(true); user.set('authData', 1234); @@ -1292,25 +1419,28 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid10', - sessionToken: 'r:123abc', - authData: { - test: { - id: 'id', - access_token: 'access_token' - } - } - }, 200); + return Promise.resolve( + { + objectId: 'uid10', + sessionToken: 'r:123abc', + authData: { + test: { + id: 'id', + access_token: 'access_token', + }, + }, + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const provider = { authenticate(options) { if (options.success) { options.success(this, { id: 'id', - access_token: 'access_token' + access_token: 'access_token', }); } }, @@ -1318,11 +1448,15 @@ describe('ParseUser', () => { getAuthType() { return 'test'; }, - deauthenticate() {} + deauthenticate() {}, }; - const user = await ParseUser._logInWith(provider, null, { useMasterKey: true }); - expect(user.get('authData')).toEqual({ test: { id: 'id', access_token: 'access_token' } }); + const user = await ParseUser._logInWith(provider, null, { + useMasterKey: true, + }); + expect(user.get('authData')).toEqual({ + test: { id: 'id', access_token: 'access_token' }, + }); }); it('can encrypt user', async () => { @@ -1340,13 +1474,16 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); u = await ParseUser.logIn('username', 'password'); // Clear cache to read from disk @@ -1392,13 +1529,16 @@ describe('ParseUser', () => { expect(body.username).toBe('username'); expect(body.password).toBe('password'); - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const CustomCrypto = { encrypt(obj, secretKey) { @@ -1440,16 +1580,22 @@ describe('ParseUser', () => { expect(path).toBe('users'); expect(options.installationId).toBe(installationId); expect(options.useMasterKey).toBe(true); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); - const user = await ParseUser.signUp('username', 'password', null, { installationId, useMasterKey: true }); + const user = await ParseUser.signUp('username', 'password', null, { + installationId, + useMasterKey: true, + }); expect(user.id).toBe('uid3'); expect(user.isCurrent()).toBe(false); expect(user.existed()).toBe(true); @@ -1464,13 +1610,16 @@ describe('ParseUser', () => { expect(method).toBe('POST'); expect(path).toBe('users'); expect(options.installationId).toBe(installationId); - return Promise.resolve({ - objectId: 'uid3', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid3', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = new ParseUser(); @@ -1487,13 +1636,16 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.verifyPassword('username', 'password'); expect(user.objectId).toBe('uid2'); @@ -1501,7 +1653,9 @@ describe('ParseUser', () => { const notStatic = new ParseUser(); notStatic.setUsername('username'); - const userAgain = await notStatic.verifyPassword('password', { useMasterKey: true }); + const userAgain = await notStatic.verifyPassword('password', { + useMasterKey: true, + }); expect(userAgain.objectId).toBe('uid2'); expect(userAgain.username).toBe('username'); @@ -1513,25 +1667,25 @@ describe('ParseUser', () => { ); return Promise.reject(parseError); }, - ajax() {} + ajax() {}, }); try { - await ParseUser.verifyPassword('username','wrong password'); - } catch(error) { + await ParseUser.verifyPassword('username', 'wrong password'); + } catch (error) { expect(error.code).toBe(101); expect(error.message).toBe('Invalid username/password.'); } try { await ParseUser.verifyPassword(null, 'password'); - } catch(error) { + } catch (error) { expect(error.code).toBe(-1); expect(error.message).toBe('Username must be a string.'); } try { await ParseUser.verifyPassword('username', null); - } catch(error) { + } catch (error) { expect(error.code).toBe(-1); expect(error.message).toBe('Password must be a string.'); } @@ -1541,27 +1695,27 @@ describe('ParseUser', () => { CoreManager.setRESTController({ request(method, path, body) { expect(method).toBe('POST'); - expect(path).toBe("verificationEmailRequest"); - expect(body).toEqual({ email: "me@parse.com" }); + expect(path).toBe('verificationEmailRequest'); + expect(body).toEqual({ email: 'me@parse.com' }); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); - ParseUser.requestEmailVerification("me@parse.com"); + ParseUser.requestEmailVerification('me@parse.com'); CoreManager.setRESTController({ request(method, path, body, options) { expect(method).toBe('POST'); - expect(path).toBe("verificationEmailRequest"); - expect(body).toEqual({ email: "me@parse.com" }); + expect(path).toBe('verificationEmailRequest'); + expect(body).toEqual({ email: 'me@parse.com' }); expect(options.useMasterKey).toBe(true); return Promise.resolve({}, 200); }, - ajax() {} + ajax() {}, }); - ParseUser.requestEmailVerification("me@parse.com", { useMasterKey: true }); + ParseUser.requestEmailVerification('me@parse.com', { useMasterKey: true }); }); it('allowCustomUserClass', () => { @@ -1581,13 +1735,16 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.logIn('username', 'password'); jest.spyOn(user, '_upgradeToRevocableSession'); @@ -1607,13 +1764,16 @@ describe('ParseUser', () => { ParseUser._clearCache(); CoreManager.setRESTController({ request() { - return Promise.resolve({ - objectId: 'uid2', - username: 'username', - sessionToken: '123abc' - }, 200); + return Promise.resolve( + { + objectId: 'uid2', + username: 'username', + sessionToken: '123abc', + }, + 200 + ); }, - ajax() {} + ajax() {}, }); const user = await ParseUser.logIn('username', 'password'); const upgradedUser = await user._upgradeToRevocableSession(); @@ -1624,7 +1784,10 @@ describe('ParseUser', () => { let CustomUser = ParseUser.extend(); expect(CustomUser instanceof ParseUser); - CustomUser = ParseUser.extend({ test: true, className: 'Item' }, { test: false, className: 'Item' }); + CustomUser = ParseUser.extend( + { test: true, className: 'Item' }, + { test: false, className: 'Item' } + ); expect(CustomUser instanceof ParseUser); const user = new CustomUser(); diff --git a/src/__tests__/Push-test.js b/src/__tests__/Push-test.js index e21271fd7..7db8014ee 100644 --- a/src/__tests__/Push-test.js +++ b/src/__tests__/Push-test.js @@ -11,15 +11,15 @@ jest.dontMock('../CoreManager'); jest.dontMock('../Push'); jest.dontMock('./test_helpers/asyncHelper'); -const mockQuery = function() { +const mockQuery = function () { this.where = {}; }; mockQuery.prototype = { toJSON() { return { - where: this.where + where: this.where, }; - } + }, }; jest.setMock('../ParseQuery', mockQuery); @@ -35,59 +35,61 @@ describe('Push', () => { send(data) { // Pipe data through so we can test it return Promise.resolve(data); - } + }, }); }); - it('can be sent with a where clause', (done) => { + it('can be sent with a where clause', done => { const q = new ParseQuery(); q.where = { - installationId: '123' + installationId: '123', }; Push.send({ - where: q - }).then((data) => { + where: q, + }).then(data => { expect(data.where).toEqual({ - installationId: '123' + installationId: '123', }); done(); }); }); - it('can specify a push time with a Date', (done) => { + it('can specify a push time with a Date', done => { Push.send({ - push_time: new Date(Date.UTC(2015, 1, 1)) - }).then((data) => { + push_time: new Date(Date.UTC(2015, 1, 1)), + }).then(data => { expect(data.push_time).toBe('2015-02-01T00:00:00.000Z'); done(); }); }); - it('can specify a push time with a string', (done) => { + it('can specify a push time with a string', done => { Push.send({ // Local timezone push - push_time: '2015-02-01T00:00:00.000' - }).then((data) => { + push_time: '2015-02-01T00:00:00.000', + }).then(data => { expect(data.push_time).toBe('2015-02-01T00:00:00.000'); done(); }); }); - it('can specify an expiration time', (done) => { + it('can specify an expiration time', done => { Push.send({ - expiration_time: new Date(Date.UTC(2015, 1, 1)) - }).then((data) => { + expiration_time: new Date(Date.UTC(2015, 1, 1)), + }).then(data => { expect(data.expiration_time).toBe('2015-02-01T00:00:00.000Z'); done(); }); }); it('cannot specify both an expiration time and an expiration interval', () => { - expect(Push.send.bind(null, { - expiration_time: new Date(), - expiration_interval: 518400 - })).toThrow('expiration_time and expiration_interval cannot both be set.'); + expect( + Push.send.bind(null, { + expiration_time: new Date(), + expiration_interval: 518400, + }) + ).toThrow('expiration_time and expiration_interval cannot both be set.'); }); }); @@ -97,25 +99,28 @@ describe('PushController', () => { const request = jest.fn().mockReturnValue({ _thenRunCallbacks() { return { - _thenRunCallbacks() {} + _thenRunCallbacks() {}, }; - } + }, }); CoreManager.setRESTController({ request: request, - ajax: function() {} + ajax: function () {}, }); - Push.send({ - push_time: new Date(Date.UTC(2015, 1, 1)) - }, { - useMasterKey: true - }); + Push.send( + { + push_time: new Date(Date.UTC(2015, 1, 1)), + }, + { + useMasterKey: true, + } + ); expect(CoreManager.getRESTController().request.mock.calls[0]).toEqual([ 'POST', 'push', { push_time: '2015-02-01T00:00:00.000Z' }, - { useMasterKey: true} + { useMasterKey: true }, ]); }); }); diff --git a/src/__tests__/RESTController-test.js b/src/__tests__/RESTController-test.js index 80cdf1040..cc6ffa8b2 100644 --- a/src/__tests__/RESTController-test.js +++ b/src/__tests__/RESTController-test.js @@ -24,7 +24,7 @@ global.wx = mockWeChat; CoreManager.setInstallationController({ currentInstallationId() { return Promise.resolve('iid'); - } + }, }); CoreManager.set('APPLICATION_ID', 'A'); CoreManager.set('JAVASCRIPT_KEY', 'B'); @@ -47,19 +47,19 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.ajax('GET', 'users/me', {}, { 'X-Parse-Session-Token': '123' }); - expect(xhr.setRequestHeader.mock.calls[0]).toEqual( - [ 'X-Parse-Session-Token', '123' ] - ); - expect(xhr.open.mock.calls[0]).toEqual([ 'GET', 'users/me', true ]); + expect(xhr.setRequestHeader.mock.calls[0]).toEqual(['X-Parse-Session-Token', '123']); + expect(xhr.open.mock.calls[0]).toEqual(['GET', 'users/me', true]); expect(xhr.send.mock.calls[0][0]).toEqual({}); }); - it('resolves with the result of the AJAX request', (done) => { - RESTController._setXHR(mockXHR([{ status: 200, response: { success: true }}])); + it('resolves with the result of the AJAX request', done => { + RESTController._setXHR(mockXHR([{ status: 200, response: { success: true } }])); RESTController.ajax('POST', 'users', {}).then(({ response, status }) => { expect(response).toEqual({ success: true }); expect(status).toBe(200); @@ -67,12 +67,10 @@ describe('RESTController', () => { }); }); - it('retries on 5XX errors', (done) => { - RESTController._setXHR(mockXHR([ - { status: 500 }, - { status: 500 }, - { status: 200, response: { success: true }} - ])); + it('retries on 5XX errors', done => { + RESTController._setXHR( + mockXHR([{ status: 500 }, { status: 500 }, { status: 200, response: { success: true } }]) + ); RESTController.ajax('POST', 'users', {}).then(({ response, status }) => { expect(response).toEqual({ success: true }); expect(status).toBe(200); @@ -81,58 +79,55 @@ describe('RESTController', () => { jest.runAllTimers(); }); - it('retries on connection failure', (done) => { - RESTController._setXHR(mockXHR([ - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - ])); - RESTController.ajax('POST', 'users', {}).then(null, (err) => { + it('retries on connection failure', done => { + RESTController._setXHR( + mockXHR([{ status: 0 }, { status: 0 }, { status: 0 }, { status: 0 }, { status: 0 }]) + ); + RESTController.ajax('POST', 'users', {}).then(null, err => { expect(err).toBe('Unable to connect to the Parse API'); done(); }); jest.runAllTimers(); }); - it('returns a connection error on network failure', async (done) => { - RESTController._setXHR(mockXHR([ - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - { status: 0 }, - ])); - RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234' }).then(null, (err) => { - expect(err.code).toBe(100); - expect(err.message).toBe('XMLHttpRequest failed: "Unable to connect to the Parse API"'); - done(); - }); - await new Promise((resolve) => setImmediate(resolve)); + it('returns a connection error on network failure', async done => { + RESTController._setXHR( + mockXHR([{ status: 0 }, { status: 0 }, { status: 0 }, { status: 0 }, { status: 0 }]) + ); + RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234' }).then( + null, + err => { + expect(err.code).toBe(100); + expect(err.message).toBe('XMLHttpRequest failed: "Unable to connect to the Parse API"'); + done(); + } + ); + await new Promise(resolve => setImmediate(resolve)); jest.runAllTimers(); }); - it('aborts after too many failures', async (done) => { - RESTController._setXHR(mockXHR([ - { status: 500 }, - { status: 500 }, - { status: 500 }, - { status: 500 }, - { status: 500 }, - { status: 200, response: { success: true }} - ])); - RESTController.ajax('POST', 'users', {}).then(null, (xhr) => { + it('aborts after too many failures', async done => { + RESTController._setXHR( + mockXHR([ + { status: 500 }, + { status: 500 }, + { status: 500 }, + { status: 500 }, + { status: 500 }, + { status: 200, response: { success: true } }, + ]) + ); + RESTController.ajax('POST', 'users', {}).then(null, xhr => { expect(xhr).not.toBe(undefined); done(); }); - await new Promise((resolve) => setImmediate(resolve)); + await new Promise(resolve => setImmediate(resolve)); jest.runAllTimers(); }); - it('rejects 1XX status codes', (done) => { + it('rejects 1XX status codes', done => { RESTController._setXHR(mockXHR([{ status: 100 }])); - RESTController.ajax('POST', 'users', {}).then(null, (xhr) => { + RESTController.ajax('POST', 'users', {}).then(null, xhr => { expect(xhr).not.toBe(undefined); done(); }); @@ -143,14 +138,18 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234' }); await flushPromises(); - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/MyObject', true] - ); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/MyObject', + true, + ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ _method: 'GET', _ApplicationId: 'A', @@ -161,140 +160,148 @@ describe('RESTController', () => { }); }); - it('handles request errors', (done) => { - RESTController._setXHR(mockXHR([{ - status: 400, response: { - code: -1, - error: 'Something bad' - } - }])); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { - expect(error.code).toBe(-1); - expect(error.message).toBe('Something bad'); - done(); - }); + it('handles request errors', done => { + RESTController._setXHR( + mockXHR([ + { + status: 400, + response: { + code: -1, + error: 'Something bad', + }, + }, + ]) + ); + RESTController.request('GET', 'classes/MyObject', {}, {}).then(null, error => { + expect(error.code).toBe(-1); + expect(error.message).toBe('Something bad'); + done(); + }); }); - it('handles invalid responses', (done) => { - const XHR = function() { }; + it('handles invalid responses', done => { + const XHR = function () {}; XHR.prototype = { - open: function() { }, - setRequestHeader: function() { }, - send: function() { + open: function () {}, + setRequestHeader: function () {}, + send: function () { this.status = 200; this.responseText = '{'; this.readyState = 4; this.onreadystatechange(); - } + }, }; RESTController._setXHR(XHR); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { - expect(error.code).toBe(100); - expect(error.message.indexOf('XMLHttpRequest failed')).toBe(0); - done(); - }); + RESTController.request('GET', 'classes/MyObject', {}, {}).then(null, error => { + expect(error.code).toBe(100); + expect(error.message.indexOf('XMLHttpRequest failed')).toBe(0); + done(); + }); }); - it('handles invalid errors', (done) => { - const XHR = function() { }; + it('handles invalid errors', done => { + const XHR = function () {}; XHR.prototype = { - open: function() { }, - setRequestHeader: function() { }, - send: function() { + open: function () {}, + setRequestHeader: function () {}, + send: function () { this.status = 400; this.responseText = '{'; this.readyState = 4; this.onreadystatechange(); - } + }, }; RESTController._setXHR(XHR); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(null, (error) => { - expect(error.code).toBe(107); - expect(error.message).toBe('Received an error with invalid JSON from Parse: {'); - done(); - }); + RESTController.request('GET', 'classes/MyObject', {}, {}).then(null, error => { + expect(error.code).toBe(107); + expect(error.message).toBe('Received an error with invalid JSON from Parse: {'); + done(); + }); }); it('handles x-parse-job-status-id header', async () => { - const XHR = function() { }; + const XHR = function () {}; XHR.prototype = { - open: function() { }, - setRequestHeader: function() { }, - getResponseHeader: function() { return 1234; }, - send: function() { + open: function () {}, + setRequestHeader: function () {}, + getResponseHeader: function () { + return 1234; + }, + send: function () { this.status = 200; this.responseText = '{}'; this.readyState = 4; this.onreadystatechange(); }, - getAllResponseHeaders: function() { + getAllResponseHeaders: function () { return 'x-parse-job-status-id: 1234'; - } + }, }; RESTController._setXHR(XHR); - const response = await RESTController.request('GET', 'classes/MyObject', {}, {}) + const response = await RESTController.request('GET', 'classes/MyObject', {}, {}); expect(response).toBe(1234); }); it('handles invalid header', async () => { - const XHR = function() { }; + const XHR = function () {}; XHR.prototype = { - open: function() { }, - setRequestHeader: function() { }, - getResponseHeader: function() { return null; }, - send: function() { + open: function () {}, + setRequestHeader: function () {}, + getResponseHeader: function () { + return null; + }, + send: function () { this.status = 200; this.responseText = '{"result":"hello"}'; this.readyState = 4; this.onreadystatechange(); }, - getAllResponseHeaders: function() { + getAllResponseHeaders: function () { return null; - } + }, }; RESTController._setXHR(XHR); - const response = await RESTController.request('GET', 'classes/MyObject', {}, {}) + const response = await RESTController.request('GET', 'classes/MyObject', {}, {}); expect(response.result).toBe('hello'); }); it('idempotency - sends requestId header', async () => { CoreManager.set('IDEMPOTENCY', true); - const requestIdHeader = (header) => 'X-Parse-Request-Id' === header[0]; + const requestIdHeader = header => 'X-Parse-Request-Id' === header[0]; const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('POST', 'classes/MyObject', {}, {}); await flushPromises(); - expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual( - [["X-Parse-Request-Id", '1000']] - ); + expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual([ + ['X-Parse-Request-Id', '1000'], + ]); xhr.setRequestHeader.mockClear(); RESTController.request('PUT', 'classes/MyObject', {}, {}); await flushPromises(); - expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual( - [["X-Parse-Request-Id", '1001']] - ); + expect(xhr.setRequestHeader.mock.calls.filter(requestIdHeader)).toEqual([ + ['X-Parse-Request-Id', '1001'], + ]); CoreManager.set('IDEMPOTENCY', false); }); - it('idempotency - handle requestId on network retries', (done) => { + it('idempotency - handle requestId on network retries', done => { CoreManager.set('IDEMPOTENCY', true); - RESTController._setXHR(mockXHR([ - { status: 500 }, - { status: 500 }, - { status: 200, response: { success: true }} - ])); + RESTController._setXHR( + mockXHR([{ status: 500 }, { status: 500 }, { status: 200, response: { success: true } }]) + ); RESTController.ajax('POST', 'users', {}).then(({ response, status, xhr }) => { // X-Parse-Request-Id should be the same for all retries - const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter((header) => 'X-Parse-Request-Id' === header[0]) - expect(requestIdHeaders.every((header) => header[1] === requestIdHeaders[0][1])).toBeTruthy(); + const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter( + header => 'X-Parse-Request-Id' === header[0] + ); + expect(requestIdHeaders.every(header => header[1] === requestIdHeaders[0][1])).toBeTruthy(); expect(requestIdHeaders.length).toBe(3); expect(response).toEqual({ success: true }); expect(status).toBe(200); @@ -309,33 +316,36 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.ajax('GET', 'users/me', {}, {}); - const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter((header) => 'X-Parse-Request-Id' === header[0]); + const requestIdHeaders = xhr.setRequestHeader.mock.calls.filter( + header => 'X-Parse-Request-Id' === header[0] + ); expect(requestIdHeaders.length).toBe(0); CoreManager.set('IDEMPOTENCY', false); }); - it('handles aborted requests', (done) => { - const XHR = function() { }; + it('handles aborted requests', done => { + const XHR = function () {}; XHR.prototype = { - open: function() { }, - setRequestHeader: function() { }, - send: function() { + open: function () {}, + setRequestHeader: function () {}, + send: function () { this.status = 0; this.responseText = '{"foo":"bar"}'; this.readyState = 4; this.onabort(); this.onreadystatechange(); - } + }, }; RESTController._setXHR(XHR); - RESTController.request('GET', 'classes/MyObject', {}, {}) - .then(() => { - done(); - }); + RESTController.request('GET', 'classes/MyObject', {}, {}).then(() => { + done(); + }); }); it('attaches the session token of the current user', async () => { @@ -360,9 +370,11 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ @@ -398,9 +410,11 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ @@ -418,9 +432,11 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); xhr.onreadystatechange(); @@ -430,7 +446,7 @@ describe('RESTController', () => { _JavaScriptKey: 'B', _ClientVersion: 'V', _InstallationId: 'iid', - _RevocableSession: '1' + _RevocableSession: '1', }); CoreManager.set('FORCE_REVOCABLE_SESSION', false); // Clean up }); @@ -440,9 +456,11 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, { useMasterKey: true }); await flushPromises(); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ @@ -454,14 +472,13 @@ describe('RESTController', () => { }); }); - it('includes the status code when requested', (done) => { - RESTController._setXHR(mockXHR([{ status: 200, response: { success: true }}])); - RESTController.request('POST', 'users', {}, { returnStatus: true }) - .then((response) => { - expect(response).toEqual(expect.objectContaining({ success: true })); - expect(response._status).toBe(200); - done(); - }); + it('includes the status code when requested', done => { + RESTController._setXHR(mockXHR([{ status: 200, response: { success: true } }])); + RESTController.request('POST', 'users', {}, { returnStatus: true }).then(response => { + expect(response).toEqual(expect.objectContaining({ success: true })); + expect(response._status).toBe(200); + done(); + }); }); it('throws when attempted to use an unprovided master key', () => { @@ -469,95 +486,107 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - expect(function() { + RESTController._setXHR(function () { + return xhr; + }); + expect(function () { RESTController.request('GET', 'classes/MyObject', {}, { useMasterKey: true }); - }).toThrow( - 'Cannot use the Master Key, it has not been provided.' - ); + }).toThrow('Cannot use the Master Key, it has not been provided.'); }); it('sends auth header when the auth type and token flags are set', async () => { CoreManager.set('SERVER_AUTH_TYPE', 'Bearer'); CoreManager.set('SERVER_AUTH_TOKEN', 'some_random_token'); - const credentialsHeader = (header) => "Authorization" === header[0]; + const credentialsHeader = header => 'Authorization' === header[0]; const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.request('GET', 'classes/MyObject', {}, {}); await flushPromises(); - expect(xhr.setRequestHeader.mock.calls.filter(credentialsHeader)).toEqual( - [["Authorization", "Bearer some_random_token"]] - ); + expect(xhr.setRequestHeader.mock.calls.filter(credentialsHeader)).toEqual([ + ['Authorization', 'Bearer some_random_token'], + ]); CoreManager.set('SERVER_AUTH_TYPE', null); CoreManager.set('SERVER_AUTH_TOKEN', null); }); - it('reports upload/download progress of the AJAX request when callback is provided', (done) => { + it('reports upload/download progress of the AJAX request when callback is provided', done => { const xhr = mockXHR([{ status: 200, response: { success: true } }], { progress: { lengthComputable: true, loaded: 5, - total: 10 - } + total: 10, + }, }); RESTController._setXHR(xhr); const options = { - progress: function(){} + progress: function () {}, }; jest.spyOn(options, 'progress'); - RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then(({ response, status }) => { - expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { type: 'download' }); - expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { type: 'upload' }); - expect(response).toEqual({ success: true }); - expect(status).toBe(200); - done(); - }); + RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then( + ({ response, status }) => { + expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { + type: 'download', + }); + expect(options.progress).toHaveBeenCalledWith(0.5, 5, 10, { + type: 'upload', + }); + expect(response).toEqual({ success: true }); + expect(status).toBe(200); + done(); + } + ); }); - it('does not upload progress when total is uncomputable', (done) => { + it('does not upload progress when total is uncomputable', done => { const xhr = mockXHR([{ status: 200, response: { success: true } }], { progress: { lengthComputable: false, loaded: 5, - total: 0 - } + total: 0, + }, }); RESTController._setXHR(xhr); const options = { - progress: function(){} + progress: function () {}, }; jest.spyOn(options, 'progress'); - RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then(({ response, status }) => { - expect(options.progress).toHaveBeenCalledWith(null, null, null, { type: 'upload' }); - expect(response).toEqual({ success: true }); - expect(status).toBe(200); - done(); - }); + RESTController.ajax('POST', 'files/upload.txt', {}, {}, options).then( + ({ response, status }) => { + expect(options.progress).toHaveBeenCalledWith(null, null, null, { + type: 'upload', + }); + expect(response).toEqual({ success: true }); + expect(status).toBe(200); + done(); + } + ); }); it('opens a XHR with the custom headers', () => { - CoreManager.set('REQUEST_HEADERS', { 'Cache-Control' : 'max-age=3600' }); + CoreManager.set('REQUEST_HEADERS', { 'Cache-Control': 'max-age=3600' }); const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); RESTController.ajax('GET', 'users/me', {}, { 'X-Parse-Session-Token': '123' }); - expect(xhr.setRequestHeader.mock.calls[3]).toEqual( - [ 'Cache-Control', 'max-age=3600' ] - ); - expect(xhr.open.mock.calls[0]).toEqual([ 'GET', 'users/me', true ]); + expect(xhr.setRequestHeader.mock.calls[3]).toEqual(['Cache-Control', 'max-age=3600']); + expect(xhr.open.mock.calls[0]).toEqual(['GET', 'users/me', true]); expect(xhr.send.mock.calls[0][0]).toEqual({}); CoreManager.set('REQUEST_HEADERS', {}); }); @@ -566,14 +595,23 @@ describe('RESTController', () => { const xhr = { setRequestHeader: jest.fn(), open: jest.fn(), - send: jest.fn() + send: jest.fn(), }; - RESTController._setXHR(function() { return xhr; }); - RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234', installationId: '5678' }); - await flushPromises(); - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/MyObject', true] + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request( + 'GET', + 'classes/MyObject', + {}, + { sessionToken: '1234', installationId: '5678' } ); + await flushPromises(); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/MyObject', + true, + ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ _method: 'GET', _ApplicationId: 'A', @@ -589,12 +627,21 @@ describe('RESTController', () => { const xhr = new XHR(); jest.spyOn(xhr, 'open'); jest.spyOn(xhr, 'send'); - RESTController._setXHR(function() { return xhr; }); - RESTController.request('GET', 'classes/MyObject', {}, { sessionToken: '1234', installationId: '5678' }); - await flushPromises(); - expect(xhr.open.mock.calls[0]).toEqual( - ['POST', 'https://api.parse.com/1/classes/MyObject', true] + RESTController._setXHR(function () { + return xhr; + }); + RESTController.request( + 'GET', + 'classes/MyObject', + {}, + { sessionToken: '1234', installationId: '5678' } ); + await flushPromises(); + expect(xhr.open.mock.calls[0]).toEqual([ + 'POST', + 'https://api.parse.com/1/classes/MyObject', + true, + ]); expect(JSON.parse(xhr.send.mock.calls[0][0])).toEqual({ _method: 'GET', _ApplicationId: 'A', @@ -611,13 +658,13 @@ describe('RESTController', () => { jest.spyOn(xhr, 'open'); jest.spyOn(xhr, 'send'); jest.spyOn(xhr, 'setRequestHeader'); - RESTController._setXHR(function() { return xhr; }); + RESTController._setXHR(function () { + return xhr; + }); const headers = { 'X-Parse-Session-Token': '123' }; RESTController.ajax('GET', 'users/me', {}, headers); - expect(xhr.setRequestHeader.mock.calls[0]).toEqual( - [ 'X-Parse-Session-Token', '123' ] - ); - expect(xhr.open.mock.calls[0]).toEqual([ 'GET', 'users/me', true ]); + expect(xhr.setRequestHeader.mock.calls[0]).toEqual(['X-Parse-Session-Token', '123']); + expect(xhr.open.mock.calls[0]).toEqual(['GET', 'users/me', true]); expect(xhr.send.mock.calls[0][0]).toEqual({}); xhr.responseHeader = headers; expect(xhr.getAllResponseHeaders().includes('X-Parse-Session-Token')).toBe(true); diff --git a/src/__tests__/SingleInstanceStateController-test.js b/src/__tests__/SingleInstanceStateController-test.js index 4bad43381..4de1c1f13 100644 --- a/src/__tests__/SingleInstanceStateController-test.js +++ b/src/__tests__/SingleInstanceStateController-test.js @@ -17,8 +17,8 @@ jest.dontMock('../promiseUtils'); jest.dontMock('../SingleInstanceStateController'); jest.dontMock('../TaskQueue'); -const mockObject = function() {}; -mockObject.registerSubclass = function() {}; +const mockObject = function () {}; +mockObject.registerSubclass = function () {}; jest.setMock('../ParseObject', mockObject); jest.useFakeTimers(); @@ -30,98 +30,189 @@ const TaskQueue = require('../TaskQueue'); describe('SingleInstanceStateController', () => { it('returns null state for an unknown object', () => { - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'someId' })).toBe(null); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'someId', + }) + ).toBe(null); }); it('returns empty data for an unknown object', () => { - expect(SingleInstanceStateController.getServerData({ className: 'someClass', id: 'someId' })).toEqual({}); + expect( + SingleInstanceStateController.getServerData({ + className: 'someClass', + id: 'someId', + }) + ).toEqual({}); }); it('returns an empty op queue for an unknown object', () => { - expect(SingleInstanceStateController.getPendingOps({ className: 'someClass', id: 'someId' })).toEqual([{}]); + expect( + SingleInstanceStateController.getPendingOps({ + className: 'someClass', + id: 'someId', + }) + ).toEqual([{}]); }); it('initializes server data when setting state', () => { - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'A' })).toBe(null); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'A' }, { counter: 12 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'A' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'A', + }) + ).toBe(null); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'A' }, + { counter: 12 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'A', + }) + ).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can clear all data', () => { - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'A' }, { counter: 12 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'A' })).toEqual({ + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'A' }, + { counter: 12 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'A', + }) + ).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); SingleInstanceStateController.clearAllState(); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'A' })).toEqual(null); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'A', + }) + ).toEqual(null); }); it('initializes server data when setting pending ops', () => { - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'B' })).toBe(null); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'B', + }) + ).toBe(null); const op = new ParseOps.IncrementOp(1); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'B' }, 'counter', op); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'B' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'B', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can set server data on an existing state', () => { - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'C' }, { counter: 12 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'C' })).toEqual({ + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'C' }, + { counter: 12 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'C', + }) + ).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false - }); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'C' }, { valid: true }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'C' })).toEqual({ + existed: false, + }); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'C' }, + { valid: true } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'C', + }) + ).toEqual({ serverData: { counter: 12, valid: true }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false - }); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'C' }, { counter: 0 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'C' })).toEqual({ + existed: false, + }); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'C' }, + { counter: 0 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'C', + }) + ).toEqual({ serverData: { counter: 0, valid: true }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can remove server data from a state', () => { - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'D' }, { counter: 12 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'D' })).toEqual({ + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'D' }, + { counter: 12 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'D', + }) + ).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false - }); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'D' }, { counter: undefined }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'D' })).toEqual({ + existed: false, + }); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'D' }, + { counter: undefined } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'D', + }) + ).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -130,168 +221,310 @@ describe('SingleInstanceStateController', () => { const op2 = new ParseOps.SetOp(true); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'counter', op); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'valid', op2); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'E' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'E', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op3 = new ParseOps.UnsetOp(); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'E' }, 'valid', op3); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'E' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'E', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op, valid: op3 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can unset pending Ops', () => { const op = new ParseOps.IncrementOp(1); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'F' }, 'counter', op); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'F' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'F', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false - }); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'F' }, 'counter', null); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'F' })).toEqual({ + existed: false, + }); + SingleInstanceStateController.setPendingOp( + { className: 'someClass', id: 'F' }, + 'counter', + null + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'F', + }) + ).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can push a new pending state frame', () => { const op = new ParseOps.IncrementOp(1); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'G' }, 'counter', op); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'G' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'G', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'G' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'G' })).toEqual({ + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'G', + }); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'G', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op2 = new ParseOps.SetOp(true); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'G' }, 'valid', op2); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'G' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'G', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }, { valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can pop a pending state frame', () => { const op = new ParseOps.IncrementOp(1); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'H' }, 'counter', op); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'H' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'H' })).toEqual({ + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'H', + }); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'H', + }) + ).toEqual({ serverData: {}, pendingOps: [{ counter: op }, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); - expect(SingleInstanceStateController.popPendingState({ className: 'someClass', id: 'H' })).toEqual({ - counter: op + expect( + SingleInstanceStateController.popPendingState({ + className: 'someClass', + id: 'H', + }) + ).toEqual({ + counter: op, }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'H' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'H', + }) + ).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('will never leave the pending Op queue empty', () => { - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'I' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'I' })).toEqual({ + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'I', + }); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'I', + }) + ).toEqual({ serverData: {}, pendingOps: [{}, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, + }); + SingleInstanceStateController.popPendingState({ + className: 'someClass', + id: 'I', + }); + SingleInstanceStateController.popPendingState({ + className: 'someClass', + id: 'I', }); - SingleInstanceStateController.popPendingState({ className: 'someClass', id: 'I' }); - SingleInstanceStateController.popPendingState({ className: 'someClass', id: 'I' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'I' })).toEqual({ + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'I', + }) + ).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can estimate a single attribute', () => { - expect(SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'unset')) - .toBe(undefined); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'J' }, { counter: 11 }); - expect(SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'counter')).toBe(11); + expect( + SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'unset') + ).toBe(undefined); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'J' }, + { counter: 11 } + ); + expect( + SingleInstanceStateController.estimateAttribute( + { className: 'someClass', id: 'J' }, + 'counter' + ) + ).toBe(11); const op = new ParseOps.IncrementOp(1); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'J' }, 'counter', op); - expect(SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'counter')).toBe(12); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'J' }); + expect( + SingleInstanceStateController.estimateAttribute( + { className: 'someClass', id: 'J' }, + 'counter' + ) + ).toBe(12); + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'J', + }); const op2 = new ParseOps.IncrementOp(10); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'J' }, 'counter', op2); - expect(SingleInstanceStateController.estimateAttribute({ className: 'someClass', id: 'J' }, 'counter')).toBe(22); + expect( + SingleInstanceStateController.estimateAttribute( + { className: 'someClass', id: 'J' }, + 'counter' + ) + ).toBe(22); }); it('can estimate all attributes', () => { - expect(SingleInstanceStateController.estimateAttributes({ className: 'someClass', id: 'K' })).toEqual({}); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'K' }, { counter: 11 }); + expect( + SingleInstanceStateController.estimateAttributes({ + className: 'someClass', + id: 'K', + }) + ).toEqual({}); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'K' }, + { counter: 11 } + ); const op = new ParseOps.IncrementOp(1); const op2 = new ParseOps.SetOp(false); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'counter', op); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'valid', op2); - expect(SingleInstanceStateController.estimateAttributes({ className: 'someClass', id: 'K' })).toEqual({ + expect( + SingleInstanceStateController.estimateAttributes({ + className: 'someClass', + id: 'K', + }) + ).toEqual({ counter: 12, - valid: false + valid: false, + }); + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'K', }); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'K' }); const op3 = new ParseOps.UnsetOp(); SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'K' }, 'valid', op3); - expect(SingleInstanceStateController.estimateAttributes({ className: 'someClass', id: 'K' })).toEqual({ - counter: 12 + expect( + SingleInstanceStateController.estimateAttributes({ + className: 'someClass', + id: 'K', + }) + ).toEqual({ + counter: 12, }); }); it('can update server data with changes', () => { - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'L' }, { counter: 11 }); - expect(SingleInstanceStateController.estimateAttributes({ className: 'someClass', id: 'L' })).toEqual({ - counter: 11 - }); - SingleInstanceStateController.commitServerChanges({ className: 'someClass', id: 'L' }, { - counter: 12, - valid: true - }); - expect(SingleInstanceStateController.estimateAttributes({ className: 'someClass', id: 'L' })).toEqual({ + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'L' }, + { counter: 11 } + ); + expect( + SingleInstanceStateController.estimateAttributes({ + className: 'someClass', + id: 'L', + }) + ).toEqual({ + counter: 11, + }); + SingleInstanceStateController.commitServerChanges( + { className: 'someClass', id: 'L' }, + { + counter: 12, + valid: true, + } + ); + expect( + SingleInstanceStateController.estimateAttributes({ + className: 'someClass', + id: 'L', + }) + ).toEqual({ counter: 12, - valid: true + valid: true, }); }); it('can enqueue a chain of tasks', async () => { let p1Resolve, p2Resolve; - const p1 = new Promise((resolve) => { p1Resolve = resolve }); - const p2 = new Promise((resolve) => { p2Resolve = resolve }); + const p1 = new Promise(resolve => { + p1Resolve = resolve; + }); + const p2 = new Promise(resolve => { + p2Resolve = resolve; + }); const called = [false, false, false]; SingleInstanceStateController.enqueueTask({ className: 'someClass', id: 'M' }, () => { return p1.then(() => { @@ -320,75 +553,137 @@ describe('SingleInstanceStateController', () => { it('can merge the first entry into the next', () => { const incCount = new ParseOps.IncrementOp(1); const setName = new ParseOps.SetOp('demo'); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'N' }, 'counter', incCount); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'N' }, 'name', setName); - SingleInstanceStateController.pushPendingState({ className: 'someClass', id: 'N' }); + SingleInstanceStateController.setPendingOp( + { className: 'someClass', id: 'N' }, + 'counter', + incCount + ); + SingleInstanceStateController.setPendingOp( + { className: 'someClass', id: 'N' }, + 'name', + setName + ); + SingleInstanceStateController.pushPendingState({ + className: 'someClass', + id: 'N', + }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'N' }, 'counter', setCount); - SingleInstanceStateController.setPendingOp({ className: 'someClass', id: 'N' }, 'valid', setValid); - SingleInstanceStateController.mergeFirstPendingState({ className: 'someClass', id: 'N' }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'N' })).toEqual({ + SingleInstanceStateController.setPendingOp( + { className: 'someClass', id: 'N' }, + 'counter', + setCount + ); + SingleInstanceStateController.setPendingOp( + { className: 'someClass', id: 'N' }, + 'valid', + setValid + ); + SingleInstanceStateController.mergeFirstPendingState({ + className: 'someClass', + id: 'N', + }); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'N', + }) + ).toEqual({ serverData: {}, - pendingOps: [{ - counter: new ParseOps.SetOp(44), - name: new ParseOps.SetOp('demo'), - valid: new ParseOps.SetOp(true), - }], + pendingOps: [ + { + counter: new ParseOps.SetOp(44), + name: new ParseOps.SetOp('demo'), + valid: new ParseOps.SetOp(true), + }, + ], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('stores cached versions of object attributes', () => { - let cache = SingleInstanceStateController.getObjectCache({ className: 'someClass', id: 'O' }); + let cache = SingleInstanceStateController.getObjectCache({ + className: 'someClass', + id: 'O', + }); expect(cache).toEqual({}); - SingleInstanceStateController.commitServerChanges({ className: 'someClass', id: 'O' }, { - name: 'MyObject', - obj: { a: 12, b: 21 }, - location: new ParseGeoPoint(20, 20), - file: ParseFile.fromJSON({ - __type: 'File', - name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' - }) + SingleInstanceStateController.commitServerChanges( + { className: 'someClass', id: 'O' }, + { + name: 'MyObject', + obj: { a: 12, b: 21 }, + location: new ParseGeoPoint(20, 20), + file: ParseFile.fromJSON({ + __type: 'File', + name: 'parse.txt', + url: 'http://files.parsetfss.com/a/parse.txt', + }), + } + ); + cache = SingleInstanceStateController.getObjectCache({ + className: 'someClass', + id: 'O', }); - cache = SingleInstanceStateController.getObjectCache({ className: 'someClass', id: 'O' }); expect(cache.name).toBe(undefined); expect(cache.file).toBe(undefined); expect(JSON.parse(cache.obj)).toEqual({ a: 12, b: 21 }); expect(JSON.parse(cache.location)).toEqual({ __type: 'GeoPoint', latitude: 20, - longitude: 20 + longitude: 20, }); }); it('can remove state for an object', () => { - expect(SingleInstanceStateController.removeState({ className: 'someClass', id: 'P' })).toBe(null); - SingleInstanceStateController.setServerData({ className: 'someClass', id: 'P' }, { counter: 12 }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'P' })).toEqual({ + expect( + SingleInstanceStateController.removeState({ + className: 'someClass', + id: 'P', + }) + ).toBe(null); + SingleInstanceStateController.setServerData( + { className: 'someClass', id: 'P' }, + { counter: 12 } + ); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'P', + }) + ).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, + }); + const state = SingleInstanceStateController.removeState({ + className: 'someClass', + id: 'P', }); - const state = SingleInstanceStateController.removeState({ className: 'someClass', id: 'P' }); expect(state).toEqual({ serverData: { counter: 12 }, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); - expect(SingleInstanceStateController.getState({ className: 'someClass', id: 'P' })).toBe(null); + expect( + SingleInstanceStateController.getState({ + className: 'someClass', + id: 'P', + }) + ).toBe(null); }); it('can duplicate the state of an object', () => { const obj = { className: 'someClass', id: 'someId' }; - SingleInstanceStateController.setServerData(obj, { counter: 12, name: 'original' }); + SingleInstanceStateController.setServerData(obj, { + counter: 12, + name: 'original', + }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); SingleInstanceStateController.setPendingOp(obj, 'counter', setCount); @@ -401,7 +696,7 @@ describe('SingleInstanceStateController', () => { pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); }); diff --git a/src/__tests__/Storage-test.js b/src/__tests__/Storage-test.js index 749a6d58a..e3030b088 100644 --- a/src/__tests__/Storage-test.js +++ b/src/__tests__/Storage-test.js @@ -43,8 +43,8 @@ const mockStorageInterface = { clear() { mockStorage = {}; - } -} + }, +}; global.localStorage = mockStorageInterface; @@ -91,91 +91,101 @@ describe('React Native StorageController', () => { expect(typeof RNStorageController.removeItemAsync).toBe('function'); }); - it('can store and retrieve values', (done) => { - RNStorageController.getItemAsync('myKey').then((result) => { - expect(result).toBe(null); - return RNStorageController.setItemAsync('myKey', 'myValue'); - }).then(() => { - return RNStorageController.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe('myValue'); - done(); - }); + it('can store and retrieve values', done => { + RNStorageController.getItemAsync('myKey') + .then(result => { + expect(result).toBe(null); + return RNStorageController.setItemAsync('myKey', 'myValue'); + }) + .then(() => { + return RNStorageController.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe('myValue'); + done(); + }); }); - it('can remove values', (done) => { - RNStorageController.setItemAsync('myKey', 'myValue').then(() => { - return RNStorageController.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe('myValue'); - return RNStorageController.removeItemAsync('myKey'); - }).then(() => { - return RNStorageController.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe(null); - done(); - }); + it('can remove values', done => { + RNStorageController.setItemAsync('myKey', 'myValue') + .then(() => { + return RNStorageController.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe('myValue'); + return RNStorageController.removeItemAsync('myKey'); + }) + .then(() => { + return RNStorageController.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe(null); + done(); + }); }); - it('can getAllKeys', (done) => { - RNStorageController.setItemAsync('myKey', 'myValue').then(() => { - return RNStorageController.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe('myValue'); - return RNStorageController.getAllKeysAsync(); - }).then((keys) => { - expect(keys[0]).toBe('myKey'); - done(); - }); + it('can getAllKeys', done => { + RNStorageController.setItemAsync('myKey', 'myValue') + .then(() => { + return RNStorageController.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe('myValue'); + return RNStorageController.getAllKeysAsync(); + }) + .then(keys => { + expect(keys[0]).toBe('myKey'); + done(); + }); }); - it('can handle set error', (done) => { + it('can handle set error', done => { const mockRNError = { setItem(path, value, cb) { cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.setItemAsync('myKey', 'myValue').catch((error) => { + RNStorageController.setItemAsync('myKey', 'myValue').catch(error => { expect(error).toBe('Error Thrown'); done(); }); }); - it('can handle get error', (done) => { + it('can handle get error', done => { const mockRNError = { getItem(path, cb) { cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.getItemAsync('myKey').catch((error) => { + RNStorageController.getItemAsync('myKey').catch(error => { expect(error).toBe('Error Thrown'); done(); }); }); - it('can handle remove error', (done) => { + it('can handle remove error', done => { const mockRNError = { removeItem(path, cb) { cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.removeItemAsync('myKey').catch((error) => { + RNStorageController.removeItemAsync('myKey').catch(error => { expect(error).toBe('Error Thrown'); done(); }); }); - it('can handle getAllKeys error', (done) => { + it('can handle getAllKeys error', done => { const mockRNError = { getAllKeys(cb) { cb('Error Thrown', undefined); }, }; CoreManager.setAsyncStorage(mockRNError); - RNStorageController.getAllKeysAsync().catch((error) => { + RNStorageController.getAllKeysAsync().catch(error => { expect(error).toBe('Error Thrown'); done(); }); @@ -260,20 +270,25 @@ describe('Storage (Default StorageController)', () => { expect(Storage.getItem('myKey')).toBe(null); }); - it('wraps synchronous methods in async wrappers', (done) => { - Storage.getItemAsync('myKey').then((result) => { - expect(result).toBe(null); - return Storage.setItemAsync('myKey', 'myValue'); - }).then(() => { - return Storage.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe('myValue'); - return Storage.removeItemAsync('myKey'); - }).then(() => { - return Storage.getItemAsync('myKey'); - }).then(() => { - done(); - }); + it('wraps synchronous methods in async wrappers', done => { + Storage.getItemAsync('myKey') + .then(result => { + expect(result).toBe(null); + return Storage.setItemAsync('myKey', 'myValue'); + }) + .then(() => { + return Storage.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe('myValue'); + return Storage.removeItemAsync('myKey'); + }) + .then(() => { + return Storage.getItemAsync('myKey'); + }) + .then(() => { + done(); + }); }); it('can generate a unique storage path', () => { @@ -302,9 +317,7 @@ describe('Storage (Default StorageController)', () => { describe('Storage (Async StorageController)', () => { beforeEach(() => { CoreManager.setAsyncStorage(mockRNStorageInterface); - CoreManager.setStorageController( - require('../StorageController.react-native') - ); + CoreManager.setStorageController(require('../StorageController.react-native')); }); it('throws when using a synchronous method', () => { @@ -322,22 +335,28 @@ describe('Storage (Async StorageController)', () => { ); }); - it('wraps synchronous methods in async wrappers', (done) => { - Storage.getItemAsync('myKey').then((result) => { - expect(result).toBe(null); - return Storage.setItemAsync('myKey', 'myValue'); - }).then(() => { - return Storage.getItemAsync('myKey'); - }).then((result) => { - expect(result).toBe('myValue'); - return Storage.getAllKeysAsync(); - }).then((result) => { - expect(result).toEqual(['myKey']); - return Storage.removeItemAsync('myKey'); - }).then(() => { - return Storage.getItemAsync('myKey'); - }).then(() => { - done(); - }); + it('wraps synchronous methods in async wrappers', done => { + Storage.getItemAsync('myKey') + .then(result => { + expect(result).toBe(null); + return Storage.setItemAsync('myKey', 'myValue'); + }) + .then(() => { + return Storage.getItemAsync('myKey'); + }) + .then(result => { + expect(result).toBe('myValue'); + return Storage.getAllKeysAsync(); + }) + .then(result => { + expect(result).toEqual(['myKey']); + return Storage.removeItemAsync('myKey'); + }) + .then(() => { + return Storage.getItemAsync('myKey'); + }) + .then(() => { + done(); + }); }); }); diff --git a/src/__tests__/TaskQueue-test.js b/src/__tests__/TaskQueue-test.js index f902bae8a..8de725b16 100644 --- a/src/__tests__/TaskQueue-test.js +++ b/src/__tests__/TaskQueue-test.js @@ -21,7 +21,7 @@ describe('TaskQueue', () => { it('runs a single task immediately', async () => { const q = new TaskQueue(); let resolve; - const p = new Promise((res) => resolve = res); + const p = new Promise(res => (resolve = res)); let called = false; let completed = false; q.enqueue(() => { @@ -33,14 +33,14 @@ describe('TaskQueue', () => { expect(called).toBe(true); expect(completed).toBe(false); resolve(); - await new Promise((resolve) => setImmediate(resolve)); + await new Promise(resolve => setImmediate(resolve)); expect(completed).toBe(true); }); - it('rejects the enqueue promise when the task errors', async (done) => { + it('rejects the enqueue promise when the task errors', async done => { const q = new TaskQueue(); let reject; - const p = new Promise((res, rej) => reject = rej); + const p = new Promise((res, rej) => (reject = rej)); let called = false; const t = q.enqueue(() => { called = true; @@ -49,12 +49,12 @@ describe('TaskQueue', () => { expect(called).toBe(true); reject('error'); try { - await t + await t; done.fail('should throw'); - } catch(e) { + } catch (e) { done(); } - }) + }); it('can execute a chain of tasks', async () => { const q = new TaskQueue(); diff --git a/src/__tests__/UniqueInstanceStateController-test.js b/src/__tests__/UniqueInstanceStateController-test.js index 2f1dcf64f..3b056ad3e 100644 --- a/src/__tests__/UniqueInstanceStateController-test.js +++ b/src/__tests__/UniqueInstanceStateController-test.js @@ -18,10 +18,10 @@ jest.dontMock('../TaskQueue'); jest.dontMock('../promiseUtils'); jest.useFakeTimers(); -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; }; -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; jest.setMock('../ParseObject', mockObject); const ParseFile = require('../ParseFile').default; @@ -57,7 +57,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -69,7 +69,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.clearAllState(); expect(UniqueInstanceStateController.getState(obj)).toEqual(null); @@ -85,7 +85,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -97,7 +97,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.setServerData(obj, { valid: true }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -105,7 +105,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.setServerData(obj, { counter: 0 }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -113,7 +113,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -125,7 +125,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.setServerData(obj, { counter: undefined }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -133,7 +133,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -148,7 +148,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op, valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op3 = new ParseOps.UnsetOp(); UniqueInstanceStateController.setPendingOp(obj, 'valid', op3); @@ -157,7 +157,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op, valid: op3 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -170,7 +170,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.setPendingOp(obj, 'counter', null); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -178,7 +178,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -191,7 +191,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.pushPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ @@ -199,7 +199,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const op2 = new ParseOps.SetOp(true); UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); @@ -208,7 +208,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }, { valid: op2 }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -222,17 +222,17 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: op }, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); expect(UniqueInstanceStateController.popPendingState(obj)).toEqual({ - counter: op + counter: op, }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -244,7 +244,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}, {}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.popPendingState(obj); UniqueInstanceStateController.popPendingState(obj); @@ -253,14 +253,13 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); it('can estimate a single attribute', () => { const obj = new ParseObject(); - expect(UniqueInstanceStateController.estimateAttribute(obj, 'unset')) - .toBe(undefined); + expect(UniqueInstanceStateController.estimateAttribute(obj, 'unset')).toBe(undefined); UniqueInstanceStateController.setServerData(obj, { counter: 11 }); expect(UniqueInstanceStateController.estimateAttribute(obj, 'counter')).toBe(11); const op = new ParseOps.IncrementOp(1); @@ -282,13 +281,13 @@ describe('UniqueInstanceStateController', () => { UniqueInstanceStateController.setPendingOp(obj, 'valid', op2); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ counter: 12, - valid: false + valid: false, }); UniqueInstanceStateController.pushPendingState(obj); const op3 = new ParseOps.UnsetOp(); UniqueInstanceStateController.setPendingOp(obj, 'valid', op3); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ - counter: 12 + counter: 12, }); }); @@ -296,15 +295,15 @@ describe('UniqueInstanceStateController', () => { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { counter: 11 }); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ - counter: 11 + counter: 11, }); UniqueInstanceStateController.commitServerChanges(obj, { counter: 12, - valid: true + valid: true, }); expect(UniqueInstanceStateController.estimateAttributes(obj)).toEqual({ counter: 12, - valid: true + valid: true, }); }); @@ -353,14 +352,16 @@ describe('UniqueInstanceStateController', () => { UniqueInstanceStateController.mergeFirstPendingState(obj); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: {}, - pendingOps: [{ - counter: new ParseOps.SetOp(44), - name: new ParseOps.SetOp('demo'), - valid: new ParseOps.SetOp(true), - }], + pendingOps: [ + { + counter: new ParseOps.SetOp(44), + name: new ParseOps.SetOp('demo'), + valid: new ParseOps.SetOp(true), + }, + ], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); }); @@ -375,8 +376,8 @@ describe('UniqueInstanceStateController', () => { file: ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' - }) + url: 'http://files.parsetfss.com/a/parse.txt', + }), }); cache = UniqueInstanceStateController.getObjectCache(obj); expect(cache.name).toBe(undefined); @@ -385,7 +386,7 @@ describe('UniqueInstanceStateController', () => { expect(JSON.parse(cache.location)).toEqual({ __type: 'GeoPoint', latitude: 20, - longitude: 20 + longitude: 20, }); }); @@ -398,7 +399,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const state = UniqueInstanceStateController.removeState(obj); expect(state).toEqual({ @@ -406,13 +407,13 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{}], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); expect(UniqueInstanceStateController.getState(obj)).toBe(null); }); it('can allocate many objects without running out of memory', () => { - const closure = function() { + const closure = function () { const obj = new ParseObject(); UniqueInstanceStateController.setServerData(obj, { spacious: true }); }; @@ -423,7 +424,10 @@ describe('UniqueInstanceStateController', () => { it('can duplicate the state of an object', () => { const obj = new ParseObject(); - UniqueInstanceStateController.setServerData(obj, { counter: 12, name: 'original' }); + UniqueInstanceStateController.setServerData(obj, { + counter: 12, + name: 'original', + }); const setCount = new ParseOps.SetOp(44); const setValid = new ParseOps.SetOp(true); UniqueInstanceStateController.setPendingOp(obj, 'counter', setCount); @@ -436,23 +440,25 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); - UniqueInstanceStateController.setServerData(duplicate, { name: 'duplicate' }); + UniqueInstanceStateController.setServerData(duplicate, { + name: 'duplicate', + }); expect(UniqueInstanceStateController.getState(obj)).toEqual({ serverData: { counter: 12, name: 'original' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ serverData: { counter: 12, name: 'duplicate' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); UniqueInstanceStateController.commitServerChanges(obj, { o: { a: 12 } }); @@ -461,14 +467,14 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: setCount, valid: setValid }], objectCache: { o: '{"a":12}' }, tasks: new TaskQueue(), - existed: false + existed: false, }); expect(UniqueInstanceStateController.getState(duplicate)).toEqual({ serverData: { counter: 12, name: 'duplicate' }, pendingOps: [{ counter: setCount, valid: setValid }], objectCache: {}, tasks: new TaskQueue(), - existed: false + existed: false, }); const otherDup = new ParseObject(); @@ -478,7 +484,7 @@ describe('UniqueInstanceStateController', () => { pendingOps: [{ counter: setCount, valid: setValid }], objectCache: { o: '{"a":12}' }, tasks: new TaskQueue(), - existed: false + existed: false, }); }); }); diff --git a/src/__tests__/arrayContainsObject-test.js b/src/__tests__/arrayContainsObject-test.js index 5e7952bf6..d53f9ff18 100644 --- a/src/__tests__/arrayContainsObject-test.js +++ b/src/__tests__/arrayContainsObject-test.js @@ -10,16 +10,16 @@ jest.dontMock('../arrayContainsObject'); let localCount = 0; -const mockObject = function(className, id) { +const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { this._localId = 'local' + localCount++; } -} -mockObject.prototype._getId = function() { +}; +mockObject.prototype._getId = function () { return this.id || this._localId; -} +}; jest.setMock('../ParseObject', mockObject); const arrayContainsObject = require('../arrayContainsObject').default; @@ -31,12 +31,12 @@ describe('arrayContainsObject', () => { expect(arrayContainsObject([], o)).toBe(false); expect(arrayContainsObject([1, 'string'], o)).toBe(false); expect(arrayContainsObject([o], o)).toBe(true); - expect(arrayContainsObject([ - new ParseObject('Item') - ], new ParseObject('Item'))).toBe(false); - expect(arrayContainsObject([ - new ParseObject('Item', 'a'), - new ParseObject('Item', 'b') - ], new ParseObject('Item', 'a'))).toBe(true); + expect(arrayContainsObject([new ParseObject('Item')], new ParseObject('Item'))).toBe(false); + expect( + arrayContainsObject( + [new ParseObject('Item', 'a'), new ParseObject('Item', 'b')], + new ParseObject('Item', 'a') + ) + ).toBe(true); }); }); diff --git a/src/__tests__/browser-test.js b/src/__tests__/browser-test.js index 3fe964f99..3b77c4d83 100644 --- a/src/__tests__/browser-test.js +++ b/src/__tests__/browser-test.js @@ -34,7 +34,9 @@ describe('Browser', () => { jest.spyOn(console, 'log').mockImplementationOnce(() => {}); jest.spyOn(Parse, '_initialize').mockImplementationOnce(() => {}); Parse.initialize('A', 'B'); - expect(console.log).toHaveBeenCalledWith("It looks like you're using the browser version of the SDK in a node.js environment. You should require('parse/node') instead."); + expect(console.log).toHaveBeenCalledWith( + "It looks like you're using the browser version of the SDK in a node.js environment. You should require('parse/node') instead." + ); expect(Parse._initialize).toHaveBeenCalledTimes(1); }); @@ -75,7 +77,13 @@ describe('Browser', () => { progress: () => {}, requestTask: () => {}, }; - const { response } = await RESTController.ajax('POST', 'classes/TestObject', null, null, options); + const { response } = await RESTController.ajax( + 'POST', + 'classes/TestObject', + null, + null, + options + ); expect(response.status).toBe(200); expect(called).toBe(true); }); @@ -101,7 +109,7 @@ describe('Browser', () => { } catch (e) { const errorResponse = JSON.stringify({ code: ParseError.X_DOMAIN_REQUEST, - error: 'IE\'s XDomainRequest does not supply error info.' + error: "IE's XDomainRequest does not supply error info.", }); expect(e.responseText).toEqual(errorResponse); } diff --git a/src/__tests__/canBeSerialized-test.js b/src/__tests__/canBeSerialized-test.js index 45a1c14da..f9a99d9d3 100644 --- a/src/__tests__/canBeSerialized-test.js +++ b/src/__tests__/canBeSerialized-test.js @@ -13,13 +13,13 @@ function mockObject(id, attributes) { this.id = id; this.attributes = attributes; } -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; jest.setMock('../ParseObject', mockObject); function mockFile(url) { this._url = url; } -mockFile.prototype.url = function() { +mockFile.prototype.url = function () { return this._url; }; jest.setMock('../ParseFile', mockFile); @@ -42,29 +42,29 @@ describe('canBeSerialized', () => { const o = new ParseObject('oid', { a: 12, b: 'string', - c: false + c: false, }); expect(canBeSerialized(o)).toBe(true); }); it('returns false when a child is an unsaved object or file', () => { let o = new ParseObject('oid', { - a: new ParseObject() + a: new ParseObject(), }); expect(canBeSerialized(o)).toBe(false); o = new ParseObject('oid', { - a: new ParseObject('oid2', {}) + a: new ParseObject('oid2', {}), }); expect(canBeSerialized(o)).toBe(true); o = new ParseObject('oid', { - a: new ParseFile() + a: new ParseFile(), }); expect(canBeSerialized(o)).toBe(false); o = new ParseObject('oid', { - a: new ParseFile('http://files.parsetfss.com/a/parse.txt') + a: new ParseFile('http://files.parsetfss.com/a/parse.txt'), }); expect(canBeSerialized(o)).toBe(true); }); @@ -72,7 +72,7 @@ describe('canBeSerialized', () => { it('returns true when all children have an id', () => { const child = new ParseObject('child', {}); const parent = new ParseObject(undefined, { - child: child + child: child, }); child.attributes.parent = parent; expect(canBeSerialized(parent)).toBe(true); @@ -92,10 +92,10 @@ describe('canBeSerialized', () => { a: { a: { a: { - b: new ParseObject() - } - } - } + b: new ParseObject(), + }, + }, + }, }); expect(canBeSerialized(o)).toBe(false); @@ -103,24 +103,34 @@ describe('canBeSerialized', () => { a: { a: { a: { - b: new ParseObject('oid2') - } - } - } + b: new ParseObject('oid2'), + }, + }, + }, }); expect(canBeSerialized(o)).toBe(true); o = new ParseObject('oid', { - a: [1, 2, 3, { - b: new ParseObject() - }] + a: [ + 1, + 2, + 3, + { + b: new ParseObject(), + }, + ], }); expect(canBeSerialized(o)).toBe(false); o = new ParseObject('oid', { - a: [1, 2, 3, { - b: new ParseObject('oid2') - }] + a: [ + 1, + 2, + 3, + { + b: new ParseObject('oid2'), + }, + ], }); expect(canBeSerialized(o)).toBe(true); }); diff --git a/src/__tests__/decode-test.js b/src/__tests__/decode-test.js index 0e6b4cfdd..47b5cc5c2 100644 --- a/src/__tests__/decode-test.js +++ b/src/__tests__/decode-test.js @@ -29,17 +29,19 @@ describe('decode', () => { }); it('decodes dates', () => { - expect(decode({ - __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' - })).toEqual(new Date(Date.UTC(2015, 1))); + expect( + decode({ + __type: 'Date', + iso: '2015-02-01T00:00:00.000Z', + }) + ).toEqual(new Date(Date.UTC(2015, 1))); }); it('decodes GeoPoints', () => { const point = decode({ __type: 'GeoPoint', latitude: 40.5, - longitude: 50.4 + longitude: 50.4, }); expect(point instanceof ParseGeoPoint).toBe(true); expect(point.latitude).toBe(40.5); @@ -47,7 +49,13 @@ describe('decode', () => { }); it('decodes Polygons', () => { - const points = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]; + const points = [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0], + ]; const polygon = decode({ __type: 'Polygon', coordinates: points, @@ -60,7 +68,7 @@ describe('decode', () => { const file = decode({ __type: 'File', name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' + url: 'https://files.parsetfss.com/a/parse.txt', }); expect(file instanceof ParseFile).toBe(true); expect(file.name()).toBe('parse.txt'); @@ -70,12 +78,9 @@ describe('decode', () => { it('decodes Relations', () => { const obj = decode({ __type: 'Relation', - className: 'Delivery' + className: 'Delivery', }); - expect(obj.constructor.mock.calls[0]).toEqual([ - null, - null - ]); + expect(obj.constructor.mock.calls[0]).toEqual([null, null]); expect(obj.targetClassName).toBe('Delivery'); }); @@ -83,7 +88,7 @@ describe('decode', () => { const data = { __type: 'Pointer', className: 'Item', - objectId: '1001' + objectId: '1001', }; decode(data); expect(ParseObject.fromJSON.mock.calls[0][0]).toEqual(data); @@ -93,33 +98,31 @@ describe('decode', () => { const data = { __type: 'Object', className: 'Item', - objectId: '1001' + objectId: '1001', }; decode(data); expect(ParseObject.fromJSON.mock.calls[1][0]).toEqual(data); }); it('iterates over arrays', () => { - expect(decode([ - { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, - 12, - 'string' - ])).toEqual([ + expect(decode([{ __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, 12, 'string'])).toEqual([ new Date(Date.UTC(2015, 1)), 12, - 'string' + 'string', ]); }); it('iterates over objects', () => { - expect(decode({ - empty: null, - when: { __type: 'Date', iso: '2015-04-01T00:00:00.000Z' }, - count: 15 - })).toEqual({ + expect( + decode({ + empty: null, + when: { __type: 'Date', iso: '2015-04-01T00:00:00.000Z' }, + count: 15, + }) + ).toEqual({ empty: null, when: new Date(Date.UTC(2015, 3)), - count: 15 + count: 15, }); }); }); diff --git a/src/__tests__/encode-test.js b/src/__tests__/encode-test.js index 5d369a177..8b5e1a1b6 100644 --- a/src/__tests__/encode-test.js +++ b/src/__tests__/encode-test.js @@ -12,10 +12,10 @@ jest.dontMock('../ParseACL'); jest.dontMock('../ParseFile'); jest.dontMock('../ParseGeoPoint'); -const mockObject = function(className) { +const mockObject = function (className) { this.className = className; }; -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; mockObject.prototype = { _getServerData() { return this._serverData; @@ -36,13 +36,13 @@ mockObject.prototype = { _toFullJSON(seen, offline) { const json = { __type: 'Object', - className: this.className + className: this.className, }; for (const attr in this.attributes) { json[attr] = encode(this.attributes[attr], false, false, seen.concat(this), offline); } return json; - } + }, }; jest.setMock('../ParseObject', mockObject); @@ -65,7 +65,7 @@ describe('encode', () => { it('encodes dates', () => { expect(encode(new Date(Date.UTC(2015, 1)))).toEqual({ __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + iso: '2015-02-01T00:00:00.000Z', }); expect(encode.bind(null, new Date(Date.parse(null)))).toThrow( 'Tried to encode an invalid date.' @@ -82,7 +82,7 @@ describe('encode', () => { expect(encode(point)).toEqual({ __type: 'GeoPoint', latitude: 40.5, - longitude: 50.4 + longitude: 50.4, }); }); @@ -93,7 +93,7 @@ describe('encode', () => { expect(encode(file)).toEqual({ __type: 'File', name: 'parse.txt', - url: 'https://files.parsetfss.com/a/parse.txt' + url: 'https://files.parsetfss.com/a/parse.txt', }); }); @@ -108,8 +108,8 @@ describe('encode', () => { expect(encode(acl)).toEqual({ aUserId: { read: true, - write: false - } + write: false, + }, }); }); @@ -120,7 +120,7 @@ describe('encode', () => { obj._serverData = obj.attributes = { str: 'string', - date: new Date(Date.UTC(2015, 1, 1)) + date: new Date(Date.UTC(2015, 1, 1)), }; expect(encode(obj)).toEqual({ __type: 'Object', @@ -128,8 +128,8 @@ describe('encode', () => { str: 'string', date: { __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' - } + iso: '2015-02-01T00:00:00.000Z', + }, }); obj.attributes.self = obj; @@ -139,9 +139,9 @@ describe('encode', () => { str: 'string', date: { __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + iso: '2015-02-01T00:00:00.000Z', }, - self: 'POINTER' + self: 'POINTER', }); }); @@ -151,7 +151,7 @@ describe('encode', () => { expect(encode(obj, false, false, undefined, true)).toEqual('OFFLINE_POINTER'); obj._serverData = obj.attributes = { str: 'string', - date: new Date(Date.UTC(2015, 1, 1)) + date: new Date(Date.UTC(2015, 1, 1)), }; obj.attributes.self = obj; @@ -161,45 +161,35 @@ describe('encode', () => { str: 'string', date: { __type: 'Date', - iso: '2015-02-01T00:00:00.000Z' + iso: '2015-02-01T00:00:00.000Z', }, - self: 'OFFLINE_POINTER' + self: 'OFFLINE_POINTER', }); }); it('does not encode ParseObjects when they are disallowed', () => { const obj = new ParseObject('Item'); - expect(encode.bind(null, obj, true)).toThrow( - 'Parse Objects not allowed here' - ); + expect(encode.bind(null, obj, true)).toThrow('Parse Objects not allowed here'); }); it('iterates over arrays', () => { let arr = [12, new Date(Date.UTC(2015, 1)), 'str']; - expect(encode(arr)).toEqual([ - 12, - { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, - 'str' - ]); + expect(encode(arr)).toEqual([12, { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, 'str']); arr = [arr]; - expect(encode(arr)).toEqual([[ - 12, - { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, - 'str' - ]]); + expect(encode(arr)).toEqual([[12, { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, 'str']]); }); it('iterates over objects', () => { const obj = { num: 12, date: new Date(Date.UTC(2015, 1)), - str: 'abc' + str: 'abc', }; expect(encode(obj)).toEqual({ num: 12, date: { __type: 'Date', iso: '2015-02-01T00:00:00.000Z' }, - str: 'abc' + str: 'abc', }); }); }); diff --git a/src/__tests__/equals-test.js b/src/__tests__/equals-test.js index 3ed942e5f..e4331f2af 100644 --- a/src/__tests__/equals-test.js +++ b/src/__tests__/equals-test.js @@ -100,12 +100,12 @@ describe('equals', () => { a = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); b = ParseFile.fromJSON({ __type: 'File', name: 'parse.txt', - url: 'http://files.parsetfss.com/a/parse.txt' + url: 'http://files.parsetfss.com/a/parse.txt', }); expect(equals(a, b)).toBe(true); diff --git a/src/__tests__/escape-test.js b/src/__tests__/escape-test.js index 0a4d7d10d..be063f6a1 100644 --- a/src/__tests__/escape-test.js +++ b/src/__tests__/escape-test.js @@ -16,12 +16,11 @@ describe('escape', () => { expect(escape('&')).toBe('&'); expect(escape('<')).toBe('<'); expect(escape('>')).toBe('>'); - expect(escape('\'')).toBe('''); + expect(escape("'")).toBe('''); expect(escape('"')).toBe('"'); expect(escape('/')).toBe('/'); // globally escapes - expect(escape('

left & right

')) - .toBe('<p>left & right</p>'); + expect(escape('

left & right

')).toBe('<p>left & right</p>'); }); }); diff --git a/src/__tests__/parseDate-test.js b/src/__tests__/parseDate-test.js index eff2e3f57..476a12af9 100644 --- a/src/__tests__/parseDate-test.js +++ b/src/__tests__/parseDate-test.js @@ -24,4 +24,4 @@ describe('parseDate', () => { it('returns null for invalid strings', () => { expect(parseDate('asdf')).toBe(null); }); -}) +}); diff --git a/src/__tests__/react-native-test.js b/src/__tests__/react-native-test.js index 3c5452bae..3d7b4cc62 100644 --- a/src/__tests__/react-native-test.js +++ b/src/__tests__/react-native-test.js @@ -9,13 +9,17 @@ jest.dontMock('../LocalDatastore'); jest.dontMock('../ParseObject'); jest.dontMock('../Storage'); -jest.mock('../../../../react-native/Libraries/vendor/emitter/EventEmitter', () => { - return { - prototype: { - addListener: new (require('events').EventEmitter)(), - }, - }; -}, { virtual: true }); +jest.mock( + '../../../../react-native/Libraries/vendor/emitter/EventEmitter', + () => { + return { + prototype: { + addListener: new (require('events').EventEmitter)(), + }, + }; + }, + { virtual: true } +); const mockEmitter = require('../../../../react-native/Libraries/vendor/emitter/EventEmitter'); const CoreManager = require('../CoreManager'); diff --git a/src/__tests__/unique-test.js b/src/__tests__/unique-test.js index 40e082513..bc30f339f 100644 --- a/src/__tests__/unique-test.js +++ b/src/__tests__/unique-test.js @@ -11,16 +11,16 @@ jest.dontMock('../arrayContainsObject'); jest.dontMock('../unique'); let localCount = 0; -const mockObject = function(className, id) { +const mockObject = function (className, id) { this.className = className; this.id = id; if (!id) { this._localId = 'local' + localCount++; } -} -mockObject.prototype._getId = function() { +}; +mockObject.prototype._getId = function () { return this.id || this._localId; -} +}; jest.setMock('../ParseObject', mockObject); const unique = require('../unique').default; @@ -39,26 +39,21 @@ describe('unique', () => { it('dedups objects by their id', () => { const o = new ParseObject('Item'); expect(unique([o, o, o])).toEqual([o]); - expect(unique([ - new ParseObject('Item'), - new ParseObject('Item') - ]).length).toBe(2); - expect(unique([ - new ParseObject('Item', 'a'), - new ParseObject('Item', 'b'), - new ParseObject('Item', 'a') - ])).toEqual([ - new ParseObject('Item', 'a'), - new ParseObject('Item', 'b') - ]); - expect(unique([ - new ParseObject('Item', 'a'), - new ParseObject('Item', 'b'), - new ParseObject('Item', 'b'), - new ParseObject('Item', 'a') - ])).toEqual([ - new ParseObject('Item', 'a'), - new ParseObject('Item', 'b') - ]); + expect(unique([new ParseObject('Item'), new ParseObject('Item')]).length).toBe(2); + expect( + unique([ + new ParseObject('Item', 'a'), + new ParseObject('Item', 'b'), + new ParseObject('Item', 'a'), + ]) + ).toEqual([new ParseObject('Item', 'a'), new ParseObject('Item', 'b')]); + expect( + unique([ + new ParseObject('Item', 'a'), + new ParseObject('Item', 'b'), + new ParseObject('Item', 'b'), + new ParseObject('Item', 'a'), + ]) + ).toEqual([new ParseObject('Item', 'a'), new ParseObject('Item', 'b')]); }); }); diff --git a/src/__tests__/unsavedChildren-test.js b/src/__tests__/unsavedChildren-test.js index c1f13ab10..d4eea094f 100644 --- a/src/__tests__/unsavedChildren-test.js +++ b/src/__tests__/unsavedChildren-test.js @@ -17,14 +17,14 @@ function mockObject({ className, localId, id, attributes, dirty }) { this.attributes = attributes; this._dirty = !!dirty; } -mockObject.registerSubclass = function() {}; +mockObject.registerSubclass = function () {}; mockObject.prototype = { _getId() { return this.id || this.localId; }, dirty() { return this._dirty; - } + }, }; jest.setMock('../ParseObject', mockObject); @@ -38,7 +38,7 @@ describe('unsavedChildren', () => { const files = [ new ParseFile('parse1.txt', [61, 170, 236, 120]), new ParseFile('parse2.txt', [61, 170, 236, 120]), - new ParseFile('parse3.txt', [61, 170, 236, 120]) + new ParseFile('parse3.txt', [61, 170, 236, 120]), ]; const f = new ParseObject({ @@ -50,27 +50,21 @@ describe('unsavedChildren', () => { c: files[2], }, }); - expect(unsavedChildren(f)).toEqual([ - files[0], files[1], files[2] - ]); + expect(unsavedChildren(f)).toEqual([files[0], files[1], files[2]]); f.attributes = { - files: files + files: files, }; - expect(unsavedChildren(f)).toEqual([ - files[0], files[1], files[2] - ]); + expect(unsavedChildren(f)).toEqual([files[0], files[1], files[2]]); f.attributes = { files: { a: files[0], b: files[1], - c: files[2] - } + c: files[2], + }, }; - expect(unsavedChildren(f)).toEqual([ - files[0], files[1], files[2] - ]); + expect(unsavedChildren(f)).toEqual([files[0], files[1], files[2]]); }); it('only returns unique files', () => { @@ -84,7 +78,7 @@ describe('unsavedChildren', () => { c: file, }, }); - expect(unsavedChildren(f)).toEqual([ file ]); + expect(unsavedChildren(f)).toEqual([file]); }); it('finds unsaved child objects', () => { @@ -92,39 +86,39 @@ describe('unsavedChildren', () => { className: 'File', localId: 'local0', attributes: {}, - dirty: true + dirty: true, }); const b = new ParseObject({ className: 'File', localId: 'local1', attributes: {}, - dirty: true + dirty: true, }); const f = new ParseObject({ className: 'Folder', id: '121', attributes: { a: a, - b: b + b: b, }, }); - expect(unsavedChildren(f)).toEqual([ a, b ]); + expect(unsavedChildren(f)).toEqual([a, b]); f.attributes = { - contents: [ a, b ] + contents: [a, b], }; - expect(unsavedChildren(f)).toEqual([ a, b ]); + expect(unsavedChildren(f)).toEqual([a, b]); f.attributes = { contents: { a: a, - b: b - } + b: b, + }, }; - expect(unsavedChildren(f)).toEqual([ a, b ]); + expect(unsavedChildren(f)).toEqual([a, b]); }); it('throws on nested objects without ids', () => { @@ -132,27 +126,25 @@ describe('unsavedChildren', () => { className: 'File', localId: 'local0', attributes: {}, - dirty: true + dirty: true, }); const b = new ParseObject({ className: 'File', localId: 'local1', attributes: { - a: a + a: a, }, - dirty: true + dirty: true, }); const f = new ParseObject({ className: 'Folder', id: '121', attributes: { - b: b + b: b, }, }); - expect(unsavedChildren.bind(null, f)).toThrow( - 'Cannot create a pointer to an unsaved Object.' - ); + expect(unsavedChildren.bind(null, f)).toThrow('Cannot create a pointer to an unsaved Object.'); }); it('can explicitly allow nested objects without ids', () => { @@ -160,25 +152,25 @@ describe('unsavedChildren', () => { className: 'Folder', localId: 'local0', dirty: true, - attributes: {} + attributes: {}, }); const b = new ParseObject({ className: 'Folder', localId: 'local1', dirty: true, - attributes: {} + attributes: {}, }); const c = new ParseObject({ className: 'File', localId: 'local2', dirty: true, - attributes: {} + attributes: {}, }); a.attributes.items = [b]; b.attributes.items = [c]; - expect(unsavedChildren(a, true)).toEqual([ b, c ]); + expect(unsavedChildren(a, true)).toEqual([b, c]); }); it('does not revisit objects', () => { @@ -190,14 +182,14 @@ describe('unsavedChildren', () => { className: 'File', localId: '131', attributes: {}, - dirty: true - }) + dirty: true, + }), }, - dirty: true + dirty: true, }); a.attributes.b.attributes.a = a; - expect(unsavedChildren(a)).toEqual([ a.attributes.b ]); + expect(unsavedChildren(a)).toEqual([a.attributes.b]); }); it('skips Relation', () => { diff --git a/src/arrayContainsObject.js b/src/arrayContainsObject.js index 791e2c2f8..17f1d927c 100644 --- a/src/arrayContainsObject.js +++ b/src/arrayContainsObject.js @@ -11,15 +11,13 @@ import ParseObject from './ParseObject'; -export default function arrayContainsObject( - array: Array, - object: ParseObject -): boolean { +export default function arrayContainsObject(array: Array, object: ParseObject): boolean { if (array.indexOf(object) > -1) { return true; } for (let i = 0; i < array.length; i++) { - if ((array[i] instanceof ParseObject) && + if ( + array[i] instanceof ParseObject && array[i].className === object.className && array[i]._getId() === object._getId() ) { diff --git a/src/decode.js b/src/decode.js index 209c80824..ac4cca011 100644 --- a/src/decode.js +++ b/src/decode.js @@ -51,7 +51,7 @@ export default function decode(value: any): any { if (value.__type === 'GeoPoint') { return new ParseGeoPoint({ latitude: value.latitude, - longitude: value.longitude + longitude: value.longitude, }); } if (value.__type === 'Polygon') { diff --git a/src/encode.js b/src/encode.js index 41e0e798a..a7800af1f 100644 --- a/src/encode.js +++ b/src/encode.js @@ -17,13 +17,20 @@ import ParseObject from './ParseObject'; import { Op } from './ParseOp'; import ParseRelation from './ParseRelation'; -function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean, seen: Array, offline: boolean): any { +function encode( + value: mixed, + disallowObjects: boolean, + forcePointers: boolean, + seen: Array, + offline: boolean +): any { if (value instanceof ParseObject) { if (disallowObjects) { throw new Error('Parse Objects not allowed here'); } const seenEntry = value.id ? value.className + ':' + value.id : value; - if (forcePointers || + if ( + forcePointers || !seen || seen.indexOf(seenEntry) > -1 || value.dirty() || @@ -37,11 +44,13 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean, seen = seen.concat(seenEntry); return value._toFullJSON(seen, offline); } - if (value instanceof Op || - value instanceof ParseACL || - value instanceof ParseGeoPoint || - value instanceof ParsePolygon || - value instanceof ParseRelation) { + if ( + value instanceof Op || + value instanceof ParseACL || + value instanceof ParseGeoPoint || + value instanceof ParsePolygon || + value instanceof ParseRelation + ) { return value.toJSON(); } if (value instanceof ParseFile) { @@ -56,13 +65,15 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean, } return { __type: 'Date', iso: (value: any).toJSON() }; } - if (Object.prototype.toString.call(value) === '[object RegExp]' && - typeof value.source === 'string') { + if ( + Object.prototype.toString.call(value) === '[object RegExp]' && + typeof value.source === 'string' + ) { return value.source; } if (Array.isArray(value)) { - return value.map((v) => { + return value.map(v => { return encode(v, disallowObjects, forcePointers, seen, offline); }); } @@ -78,6 +89,12 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean, return value; } -export default function(value: mixed, disallowObjects?: boolean, forcePointers?: boolean, seen?: Array, offline?: boolean): any { +export default function ( + value: mixed, + disallowObjects?: boolean, + forcePointers?: boolean, + seen?: Array, + offline?: boolean +): any { return encode(value, !!disallowObjects, !!forcePointers, seen || [], offline); } diff --git a/src/equals.js b/src/equals.js index dc83beb6e..8080f9c39 100644 --- a/src/equals.js +++ b/src/equals.js @@ -17,7 +17,7 @@ export default function equals(a, b) { if (toString.call(a) === '[object Date]' || toString.call(b) === '[object Date]') { const dateA = new Date(a); const dateB = new Date(b); - return (+dateA === +dateB); + return +dateA === +dateB; } if (typeof a !== typeof b) { @@ -26,7 +26,7 @@ export default function equals(a, b) { if (!a || typeof a !== 'object') { // a is a primitive - return (a === b); + return a === b; } if (Array.isArray(a) || Array.isArray(b)) { @@ -44,10 +44,12 @@ export default function equals(a, b) { return true; } - if ((a instanceof ParseACL) || - (a instanceof ParseFile) || - (a instanceof ParseGeoPoint) || - (a instanceof ParseObject)) { + if ( + a instanceof ParseACL || + a instanceof ParseFile || + a instanceof ParseGeoPoint || + a instanceof ParseObject + ) { return a.equals(b); } if (b instanceof ParseObject) { diff --git a/src/escape.js b/src/escape.js index a56eeb1f3..2445e6d2d 100644 --- a/src/escape.js +++ b/src/escape.js @@ -14,12 +14,12 @@ const encoded = { '<': '<', '>': '>', '/': '/', - '\'': ''', - '"': '"' + "'": ''', + '"': '"', }; export default function escape(str: string): string { - return str.replace(/[&<>\/'"]/g, function(char) { + return str.replace(/[&<>\/'"]/g, function (char) { return encoded[char]; }); } diff --git a/src/interfaces/react-native.js b/src/interfaces/react-native.js index 346d35c40..08b8a0e95 100644 --- a/src/interfaces/react-native.js +++ b/src/interfaces/react-native.js @@ -10,7 +10,7 @@ /** * Interface declaration for React Native modules */ -declare module "react-native" { +declare module 'react-native' { declare class AsyncStorage { static getItem(path: string, cb: (err: string, value: string) => void): void; static setItem(path: string, value: string, cb: (err: string, value: string) => void): void; diff --git a/src/parseDate.js b/src/parseDate.js index 936fb602e..e6bde1a85 100644 --- a/src/parseDate.js +++ b/src/parseDate.js @@ -11,9 +11,12 @@ export default function parseDate(iso8601: string): ?Date { const regexp = new RegExp( - '^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})' + 'T' + - '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})' + - '(.([0-9]+))?' + 'Z$'); + '^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})' + + 'T' + + '([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})' + + '(.([0-9]+))?' + + 'Z$' + ); const match = regexp.exec(iso8601); if (!match) { return null; diff --git a/src/promiseUtils.js b/src/promiseUtils.js index dadca7c33..176c32a0b 100644 --- a/src/promiseUtils.js +++ b/src/promiseUtils.js @@ -34,7 +34,7 @@ export function when(promises) { const promise = new resolvingPromise(); - const resolveOne = function() { + const resolveOne = function () { total--; if (total <= 0) { if (hadError) { @@ -45,16 +45,19 @@ export function when(promises) { } }; - const chain = function(object, index) { - if (object && typeof object.then === 'function') { - object.then(function(result) { - results[index] = result; - resolveOne(); - }, function(error) { - errors[index] = error; - hadError = true; - resolveOne(); - }); + const chain = function (object, index) { + if (object && typeof object.then === 'function') { + object.then( + function (result) { + results[index] = result; + resolveOne(); + }, + function (error) { + errors[index] = error; + hadError = true; + resolveOne(); + } + ); } else { results[index] = object; resolveOne(); diff --git a/src/unique.js b/src/unique.js index cfeea4b41..655a362f9 100644 --- a/src/unique.js +++ b/src/unique.js @@ -14,7 +14,7 @@ import ParseObject from './ParseObject'; export default function unique(arr: Array): Array { const uniques = []; - arr.forEach((value) => { + arr.forEach(value => { if (value instanceof ParseObject) { if (!arrayContainsObject(uniques, value)) { uniques.push(value); diff --git a/src/unsavedChildren.js b/src/unsavedChildren.js index 512173efa..6596e5a38 100644 --- a/src/unsavedChildren.js +++ b/src/unsavedChildren.js @@ -14,8 +14,8 @@ import ParseObject from './ParseObject'; import ParseRelation from './ParseRelation'; type EncounterMap = { - objects: { [identifier: string]: ParseObject | boolean; }; - files: Array; + objects: { [identifier: string]: ParseObject | boolean }, + files: Array, }; /** @@ -32,12 +32,10 @@ export default function unsavedChildren( ): Array { const encountered = { objects: {}, - files: [] + files: [], }; const identifier = obj.className + ':' + obj._getId(); - encountered.objects[identifier] = ( - obj.dirty() ? obj : true - ); + encountered.objects[identifier] = obj.dirty() ? obj : true; const attributes = obj.attributes; for (const attr in attributes) { if (typeof attributes[attr] === 'object') { @@ -65,9 +63,7 @@ function traverse( } const identifier = obj.className + ':' + obj._getId(); if (!encountered.objects[identifier]) { - encountered.objects[identifier] = ( - obj.dirty() ? obj : true - ); + encountered.objects[identifier] = obj.dirty() ? obj : true; const attributes = obj.attributes; for (const attr in attributes) { if (typeof attributes[attr] === 'object') { @@ -87,7 +83,7 @@ function traverse( return; } if (Array.isArray(obj)) { - obj.forEach((el) => { + obj.forEach(el => { if (typeof el === 'object') { traverse(el, encountered, shouldThrow, allowDeepUnsaved); }